Matthew Treinish | 9e26ca8 | 2016-02-23 11:43:20 -0500 | [diff] [blame] | 1 | # Copyright 2012 OpenStack Foundation |
| 2 | # All Rights Reserved. |
| 3 | # |
| 4 | # Licensed under the Apache License, Version 2.0 (the "License"); you may |
| 5 | # not use this file except in compliance with the License. You may obtain |
| 6 | # a copy of the License at |
| 7 | # |
| 8 | # http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | # |
| 10 | # Unless required by applicable law or agreed to in writing, software |
| 11 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| 12 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
| 13 | # License for the specific language governing permissions and limitations |
| 14 | # under the License. |
| 15 | |
| 16 | import itertools |
| 17 | import netaddr |
| 18 | import random |
| 19 | import string |
| 20 | import uuid |
| 21 | |
Yatin Kumbhare | ee4924c | 2016-06-09 15:12:06 +0530 | [diff] [blame] | 22 | from oslo_utils import netutils |
Jordan Pittier | 4408c4a | 2016-04-29 15:05:09 +0200 | [diff] [blame] | 23 | import six.moves |
| 24 | |
Matthew Treinish | 9e26ca8 | 2016-02-23 11:43:20 -0500 | [diff] [blame] | 25 | |
| 26 | def rand_uuid(): |
| 27 | """Generate a random UUID string |
| 28 | |
| 29 | :return: a random UUID (e.g. '1dc12c7d-60eb-4b61-a7a2-17cf210155b6') |
| 30 | :rtype: string |
| 31 | """ |
| 32 | return str(uuid.uuid4()) |
| 33 | |
| 34 | |
| 35 | def rand_uuid_hex(): |
| 36 | """Generate a random UUID hex string |
| 37 | |
| 38 | :return: a random UUID (e.g. '0b98cf96d90447bda4b46f31aeb1508c') |
| 39 | :rtype: string |
| 40 | """ |
| 41 | return uuid.uuid4().hex |
| 42 | |
| 43 | |
| 44 | def rand_name(name='', prefix=None): |
zhufl | 0892cb2 | 2016-05-06 14:46:00 +0800 | [diff] [blame] | 45 | """Generate a random name that includes a random number |
Matthew Treinish | 9e26ca8 | 2016-02-23 11:43:20 -0500 | [diff] [blame] | 46 | |
| 47 | :param str name: The name that you want to include |
| 48 | :param str prefix: The prefix that you want to include |
| 49 | :return: a random name. The format is |
| 50 | '<prefix>-<random number>-<name>-<random number>'. |
| 51 | (e.g. 'prefixfoo-1308607012-namebar-154876201') |
| 52 | :rtype: string |
| 53 | """ |
| 54 | randbits = str(random.randint(1, 0x7fffffff)) |
| 55 | rand_name = randbits |
| 56 | if name: |
| 57 | rand_name = name + '-' + rand_name |
| 58 | if prefix: |
| 59 | rand_name = prefix + '-' + rand_name |
| 60 | return rand_name |
| 61 | |
| 62 | |
| 63 | def rand_password(length=15): |
| 64 | """Generate a random password |
| 65 | |
| 66 | :param int length: The length of password that you expect to set |
| 67 | (If it's smaller than 3, it's same as 3.) |
| 68 | :return: a random password. The format is |
| 69 | '<random upper letter>-<random number>-<random special character> |
| 70 | -<random ascii letters or digit characters or special symbols>' |
| 71 | (e.g. 'G2*ac8&lKFFgh%2') |
| 72 | :rtype: string |
| 73 | """ |
| 74 | upper = random.choice(string.ascii_uppercase) |
| 75 | ascii_char = string.ascii_letters |
| 76 | digits = string.digits |
| 77 | digit = random.choice(string.digits) |
| 78 | puncs = '~!@#$%^&*_=+' |
| 79 | punc = random.choice(puncs) |
| 80 | seed = ascii_char + digits + puncs |
| 81 | pre = upper + digit + punc |
| 82 | password = pre + ''.join(random.choice(seed) for x in range(length - 3)) |
| 83 | return password |
| 84 | |
| 85 | |
| 86 | def rand_url(): |
zhufl | 0892cb2 | 2016-05-06 14:46:00 +0800 | [diff] [blame] | 87 | """Generate a random url that includes a random number |
Matthew Treinish | 9e26ca8 | 2016-02-23 11:43:20 -0500 | [diff] [blame] | 88 | |
| 89 | :return: a random url. The format is 'https://url-<random number>.com'. |
| 90 | (e.g. 'https://url-154876201.com') |
| 91 | :rtype: string |
| 92 | """ |
| 93 | randbits = str(random.randint(1, 0x7fffffff)) |
| 94 | return 'https://url-' + randbits + '.com' |
| 95 | |
| 96 | |
| 97 | def rand_int_id(start=0, end=0x7fffffff): |
| 98 | """Generate a random integer value |
| 99 | |
| 100 | :param int start: The value that you expect to start here |
| 101 | :param int end: The value that you expect to end here |
| 102 | :return: a random integer value |
| 103 | :rtype: int |
| 104 | """ |
| 105 | return random.randint(start, end) |
| 106 | |
| 107 | |
| 108 | def rand_mac_address(): |
| 109 | """Generate an Ethernet MAC address |
| 110 | |
| 111 | :return: an random Ethernet MAC address |
| 112 | :rtype: string |
| 113 | """ |
| 114 | # NOTE(vish): We would prefer to use 0xfe here to ensure that linux |
| 115 | # bridge mac addresses don't change, but it appears to |
| 116 | # conflict with libvirt, so we use the next highest octet |
| 117 | # that has the unicast and locally administered bits set |
| 118 | # properly: 0xfa. |
| 119 | # Discussion: https://bugs.launchpad.net/nova/+bug/921838 |
| 120 | mac = [0xfa, 0x16, 0x3e, |
| 121 | random.randint(0x00, 0xff), |
| 122 | random.randint(0x00, 0xff), |
| 123 | random.randint(0x00, 0xff)] |
| 124 | return ':'.join(["%02x" % x for x in mac]) |
| 125 | |
| 126 | |
Lenny Verkhovsky | 92b46e3 | 2016-03-14 13:14:58 +0200 | [diff] [blame] | 127 | def rand_infiniband_guid_address(): |
| 128 | """Generate an Infiniband GUID address |
| 129 | |
| 130 | :return: an random Infiniband GUID address |
| 131 | :rtype: string |
| 132 | """ |
| 133 | guid = [] |
| 134 | for i in range(8): |
| 135 | guid.append("%02x" % random.randint(0x00, 0xff)) |
| 136 | return ':'.join(guid) |
| 137 | |
| 138 | |
Matthew Treinish | 9e26ca8 | 2016-02-23 11:43:20 -0500 | [diff] [blame] | 139 | def parse_image_id(image_ref): |
| 140 | """Return the image id from a given image ref |
| 141 | |
| 142 | This function just returns the last word of the given image ref string |
| 143 | splitting with '/'. |
| 144 | :param str image_ref: a string that includes the image id |
| 145 | :return: the image id string |
| 146 | :rtype: string |
| 147 | """ |
| 148 | return image_ref.rsplit('/')[-1] |
| 149 | |
| 150 | |
| 151 | def arbitrary_string(size=4, base_text=None): |
| 152 | """Return size characters from base_text |
| 153 | |
| 154 | This generates a string with an arbitrary number of characters, generated |
| 155 | by looping the base_text string. If the size is smaller than the size of |
| 156 | base_text, returning string is shrinked to the size. |
Pablo Sanchez | deabf43 | 2016-06-23 09:58:42 +0200 | [diff] [blame] | 157 | :param int size: a returning characters size |
Matthew Treinish | 9e26ca8 | 2016-02-23 11:43:20 -0500 | [diff] [blame] | 158 | :param str base_text: a string you want to repeat |
| 159 | :return: size string |
| 160 | :rtype: string |
| 161 | """ |
| 162 | if not base_text: |
| 163 | base_text = 'test' |
| 164 | return ''.join(itertools.islice(itertools.cycle(base_text), size)) |
| 165 | |
| 166 | |
| 167 | def random_bytes(size=1024): |
| 168 | """Return size randomly selected bytes as a string |
| 169 | |
| 170 | :param int size: a returning bytes size |
| 171 | :return: size randomly bytes |
| 172 | :rtype: string |
| 173 | """ |
| 174 | return ''.join([chr(random.randint(0, 255)) |
| 175 | for i in range(size)]) |
| 176 | |
| 177 | |
| 178 | def get_ipv6_addr_by_EUI64(cidr, mac): |
| 179 | """Generate a IPv6 addr by EUI-64 with CIDR and MAC |
| 180 | |
| 181 | :param str cidr: a IPv6 CIDR |
| 182 | :param str mac: a MAC address |
| 183 | :return: an IPv6 Address |
| 184 | :rtype: netaddr.IPAddress |
| 185 | """ |
| 186 | # Check if the prefix is IPv4 address |
Yatin Kumbhare | ee4924c | 2016-06-09 15:12:06 +0530 | [diff] [blame] | 187 | is_ipv4 = netutils.is_valid_ipv4(cidr) |
Matthew Treinish | 9e26ca8 | 2016-02-23 11:43:20 -0500 | [diff] [blame] | 188 | if is_ipv4: |
| 189 | msg = "Unable to generate IP address by EUI64 for IPv4 prefix" |
| 190 | raise TypeError(msg) |
| 191 | try: |
| 192 | eui64 = int(netaddr.EUI(mac).eui64()) |
| 193 | prefix = netaddr.IPNetwork(cidr) |
| 194 | return netaddr.IPAddress(prefix.first + eui64 ^ (1 << 57)) |
| 195 | except (ValueError, netaddr.AddrFormatError): |
| 196 | raise TypeError('Bad prefix or mac format for generating IPv6 ' |
| 197 | 'address by EUI-64: %(prefix)s, %(mac)s:' |
| 198 | % {'prefix': cidr, 'mac': mac}) |
| 199 | except TypeError: |
| 200 | raise TypeError('Bad prefix type for generate IPv6 address by ' |
| 201 | 'EUI-64: %s' % cidr) |
Jordan Pittier | 4408c4a | 2016-04-29 15:05:09 +0200 | [diff] [blame] | 202 | |
| 203 | |
| 204 | # Courtesy of http://stackoverflow.com/a/312464 |
| 205 | def chunkify(sequence, chunksize): |
| 206 | """Yield successive chunks from `sequence`.""" |
| 207 | for i in six.moves.xrange(0, len(sequence), chunksize): |
| 208 | yield sequence[i:i + chunksize] |