1# -*- coding: utf-8 -*- 2# Copyright 2011 Google Inc. All Rights Reserved. 3# 4# Licensed under the Apache License, Version 2.0 (the "License"); 5# you may not use this file except in compliance with the License. 6# You may obtain 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, 12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13# See the License for the specific language governing permissions and 14# limitations under the License. 15"""Implementation of mb command for creating cloud storage buckets.""" 16 17from __future__ import absolute_import 18 19import textwrap 20 21from gslib.cloud_api import BadRequestException 22from gslib.command import Command 23from gslib.command_argument import CommandArgument 24from gslib.cs_api_map import ApiSelector 25from gslib.exception import CommandException 26from gslib.storage_url import StorageUrlFromString 27from gslib.third_party.storage_apitools import storage_v1_messages as apitools_messages 28from gslib.util import NO_MAX 29 30 31_SYNOPSIS = """ 32 gsutil mb [-c class] [-l location] [-p proj_id] uri... 33""" 34 35_DETAILED_HELP_TEXT = (""" 36<B>SYNOPSIS</B> 37""" + _SYNOPSIS + """ 38 39 40<B>DESCRIPTION</B> 41 The mb command creates a new bucket. Google Cloud Storage has a single 42 namespace, so you will not be allowed to create a bucket with a name already 43 in use by another user. You can, however, carve out parts of the bucket name 44 space corresponding to your company's domain name (see "gsutil help naming"). 45 46 If you don't specify a project ID using the -p option, the bucket 47 will be created using the default project ID specified in your gsutil 48 configuration file (see "gsutil help config"). For more details about 49 projects see "gsutil help projects". 50 51 The -c and -l options specify the storage class and location, respectively, 52 for the bucket. Once a bucket is created in a given location and with a 53 given storage class, it cannot be moved to a different location, and the 54 storage class cannot be changed. Instead, you would need to create a new 55 bucket and move the data over and then delete the original bucket. 56 57 58<B>BUCKET STORAGE CLASSES</B> 59 If you don't specify a -c option, the bucket will be created with the default 60 (Standard) storage class. 61 62 If you specify -c DURABLE_REDUCED_AVAILABILITY (or -c DRA), it causes the data 63 stored in the bucket to use Durable Reduced Availability storage. Buckets 64 created with this storage class have lower availability than Standard storage 65 class buckets, but durability equal to that of buckets created with Standard 66 storage class. This option allows users to reduce costs for data for which 67 lower availability is acceptable. Durable Reduced Availability storage would 68 not be appropriate for "hot" objects (i.e., objects being accessed frequently) 69 or for interactive workloads; however, it might be appropriate for other types 70 of applications. See the online documentation for 71 `pricing <https://cloud.google.com/storage/pricing>`_ 72 and `SLA <https://cloud.google.com/storage/sla>`_ 73 details. 74 75 76 If you specify -c NEARLINE (or -c NL), it causes the data 77 stored in the bucket to use Nearline storage. Buckets created with this 78 storage class have higher latency and lower throughput than Standard storage 79 class buckets. The availability and durability remains equal to that of 80 buckets created with the Standard storage class. This option is best for 81 objects which are accessed rarely and for which slower performance is 82 acceptable. See the online documentation for 83 `pricing <https://cloud.google.com/storage/pricing>`_ and 84 `SLA <https://cloud.google.com/storage/sla>`_ details. 85 86 87<B>BUCKET LOCATIONS</B> 88 If you don't specify a -l option, the bucket will be created in the default 89 location (US). Otherwise, you can specify one of the available continental 90 locations: 91 92 - ASIA (Asia) 93 - EU (European Union) 94 - US (United States) 95 96 Example: 97 gsutil mb -l ASIA gs://some-bucket 98 99 If you specify the Durable Reduced Availability storage class (-c DRA), you 100 can specify one of the continental locations above or one of the regional 101 locations below: [1]_ 102 103 - ASIA-EAST1 (Eastern Asia-Pacific) 104 - US-EAST1 (Eastern United States) 105 - US-EAST2 (Eastern United States) 106 - US-EAST3 (Eastern United States) 107 - US-CENTRAL1 (Central United States) 108 - US-CENTRAL2 (Central United States) 109 - US-WEST1 (Western United States) 110 111 Example: 112 gsutil mb -c DRA -l US-CENTRAL1 gs://some-bucket 113 114 .. [1] These locations are for `Regional Buckets <https://developers.google.com/storage/docs/regional-buckets>`_. 115 Regional Buckets is an experimental feature and data stored in these 116 locations is not subject to the usual SLA. See the documentation for 117 additional information. 118 119 120<B>OPTIONS</B> 121 -c class Can be DRA (or DURABLE_REDUCED_AVAILABILITY), NL (or 122 NEARLINE), or S (or STANDARD). Default is STANDARD. 123 124 -l location Can be any continental location as described above, or 125 for DRA storage class, any regional or continental 126 location. Default is US. Locations are case insensitive. 127 128 -p proj_id Specifies the project ID under which to create the bucket. 129""") 130 131 132class MbCommand(Command): 133 """Implementation of gsutil mb command.""" 134 135 # Command specification. See base class for documentation. 136 command_spec = Command.CreateCommandSpec( 137 'mb', 138 command_name_aliases=['makebucket', 'createbucket', 'md', 'mkdir'], 139 usage_synopsis=_SYNOPSIS, 140 min_args=1, 141 max_args=NO_MAX, 142 supported_sub_args='c:l:p:', 143 file_url_ok=False, 144 provider_url_ok=False, 145 urls_start_arg=0, 146 gs_api_support=[ApiSelector.XML, ApiSelector.JSON], 147 gs_default_api=ApiSelector.JSON, 148 argparse_arguments=[ 149 CommandArgument.MakeZeroOrMoreCloudBucketURLsArgument() 150 ] 151 ) 152 # Help specification. See help_provider.py for documentation. 153 help_spec = Command.HelpSpec( 154 help_name='mb', 155 help_name_aliases=[ 156 'createbucket', 'makebucket', 'md', 'mkdir', 'location', 'dra', 157 'dras', 'reduced_availability', 'durable_reduced_availability', 'rr', 158 'reduced_redundancy', 'standard', 'storage class', 'nearline', 'nl'], 159 help_type='command_help', 160 help_one_line_summary='Make buckets', 161 help_text=_DETAILED_HELP_TEXT, 162 subcommand_help_text={}, 163 ) 164 165 def RunCommand(self): 166 """Command entry point for the mb command.""" 167 location = None 168 storage_class = None 169 if self.sub_opts: 170 for o, a in self.sub_opts: 171 if o == '-l': 172 location = a 173 elif o == '-p': 174 self.project_id = a 175 elif o == '-c': 176 storage_class = self._Normalize_Storage_Class(a) 177 178 bucket_metadata = apitools_messages.Bucket(location=location, 179 storageClass=storage_class) 180 181 for bucket_uri_str in self.args: 182 bucket_uri = StorageUrlFromString(bucket_uri_str) 183 if not bucket_uri.IsBucket(): 184 raise CommandException('The mb command requires a URI that specifies a ' 185 'bucket.\n"%s" is not valid.' % bucket_uri) 186 187 self.logger.info('Creating %s...', bucket_uri) 188 # Pass storage_class param only if this is a GCS bucket. (In S3 the 189 # storage class is specified on the key object.) 190 try: 191 self.gsutil_api.CreateBucket( 192 bucket_uri.bucket_name, project_id=self.project_id, 193 metadata=bucket_metadata, provider=bucket_uri.scheme) 194 except BadRequestException as e: 195 if (e.status == 400 and e.reason == 'DotfulBucketNameNotUnderTld' and 196 bucket_uri.scheme == 'gs'): 197 bucket_name = bucket_uri.bucket_name 198 final_comp = bucket_name[bucket_name.rfind('.')+1:] 199 raise CommandException('\n'.join(textwrap.wrap( 200 'Buckets with "." in the name must be valid DNS names. The bucket' 201 ' you are attempting to create (%s) is not a valid DNS name,' 202 ' because the final component (%s) is not currently a valid part' 203 ' of the top-level DNS tree.' % (bucket_name, final_comp)))) 204 else: 205 raise 206 207 return 0 208 209 def _Normalize_Storage_Class(self, sc): 210 sc = sc.upper() 211 if sc in ('DRA', 'DURABLE_REDUCED_AVAILABILITY'): 212 return 'DURABLE_REDUCED_AVAILABILITY' 213 if sc in ('S', 'STD', 'STANDARD'): 214 return 'STANDARD' 215 if sc in ('NL', 'NEARLINE'): 216 return 'NEARLINE' 217 return sc 218