@@ -195,7 +198,7 @@
-Generated on Thu Oct 24 2013 09:26:02 for pyrax by
+Generated on Wed Mar 12 2014 16:01:43 for pyrax by 1.7.6.1
diff --git a/docs/html/annotated.html b/docs/html/annotated.html
index 84ea3b9b..bc828fd6 100644
--- a/docs/html/annotated.html
+++ b/docs/html/annotated.html
@@ -196,6 +196,11 @@
@@ -346,7 +364,7 @@
-Generated on Mon Feb 24 2014 11:18:02 for pyrax by
+Generated on Wed Mar 12 2014 16:01:48 for pyrax by 1.7.6.1
diff --git a/docs/html/classes.html b/docs/html/classes.html
index dae38a34..7c207543 100644
--- a/docs/html/classes.html
+++ b/docs/html/classes.html
@@ -82,88 +82,93 @@
-Generated on Mon Feb 24 2014 11:18:03 for pyrax by
+Generated on Wed Mar 12 2014 16:01:48 for pyrax by 1.7.6.1
diff --git a/docs/html/classpyrax_1_1client_1_1BaseClient.html b/docs/html/classpyrax_1_1client_1_1BaseClient.html
index 5077e3c8..c690cdba 100644
--- a/docs/html/classpyrax_1_1client_1_1BaseClient.html
+++ b/docs/html/classpyrax_1_1client_1_1BaseClient.html
@@ -124,7 +124,8 @@
-
+
+
@@ -985,7 +986,7 @@
Accepts an image reference (object or ID) and dictionary of key/value pairs, where the key is an attribute of the image, and the value is the desired new value for that image.
Pagination is supported through the optional 'marker' and 'limit' parameters. Filtering the returned value is possible by specifying values for any of the other parameters.
Accepts an image reference (object or ID) and dictionary of key/value pairs, where the key is an attribute of the image, and the value is the desired new value for that image.
Updates the image whose ID is given with the status specified.
+
This must be called by the user whose project_id is in the members for the image; that is, the user with whom the image is being shared. If called by the owner of the image, an `InvalidImageMember` exception will be raised.
+
Valid values for 'status' include: pending accepted rejected
+
Any other value will result in an `InvalidImageMemberStatus` exception being raised.
Accepts an image reference (object or ID) and dictionary of key/value pairs, where the key is an attribute of the image, and the value is the desired new value for that image.
Pagination is supported through the optional 'marker' and 'limit' parameters. Filtering the returned value is possible by specifying values for any of the other parameters.
Accepts an image reference (object or ID) and dictionary of key/value pairs, where the key is an attribute of the image, and the value is the desired new value for that image.
+
NOTE: There is a bug in Glance where the 'add' operation returns a 409 if the property already exists, which conflicts with the spec. So to get around this a fresh copy of the image must be retrieved, and the value of 'op' must be determined based on whether this attribute exists or not.
Updates the image whose ID is given with the status specified.
+
This must be called by the user whose project_id is in the members for the image. If called by the owner of the image, an InvalidImageMember exception will be raised.
+
Valid values for 'status' include: pending accepted rejected Any other value will result in an InvalidImageMemberStatus exception being raised.
+
+
+
+The documentation for this class was generated from the following file:
@@ -235,7 +239,7 @@
-Generated on Mon Feb 24 2014 11:17:57 for pyrax by
+Generated on Wed Mar 12 2014 16:01:43 for pyrax by 1.7.6.1
diff --git a/docs/html/fakes_8py.html b/docs/html/fakes_8py.html
index ff1c2543..a7970b6d 100644
--- a/docs/html/fakes_8py.html
+++ b/docs/html/fakes_8py.html
@@ -140,6 +140,11 @@
@@ -180,7 +185,7 @@
-Generated on Mon Feb 24 2014 11:17:57 for pyrax by
+Generated on Wed Mar 12 2014 16:01:43 for pyrax by 1.7.6.1
diff --git a/docs/html/files.html b/docs/html/files.html
index d5ac7caf..d9b52403 100644
--- a/docs/html/files.html
+++ b/docs/html/files.html
@@ -93,6 +93,7 @@
@@ -125,7 +126,7 @@
-Generated on Mon Feb 24 2014 11:18:03 for pyrax by
+Generated on Wed Mar 12 2014 16:01:49 for pyrax by 1.7.6.1
diff --git a/docs/html/functions.html b/docs/html/functions.html
index 39cc1d7c..087a23ea 100644
--- a/docs/html/functions.html
+++ b/docs/html/functions.html
@@ -141,9 +141,15 @@
-Generated on Mon Feb 24 2014 11:18:03 for pyrax by
+Generated on Wed Mar 12 2014 16:01:48 for pyrax by 1.7.6.1
diff --git a/docs/html/functions_0x61.html b/docs/html/functions_0x61.html
index 17ee0351..e84076af 100644
--- a/docs/html/functions_0x61.html
+++ b/docs/html/functions_0x61.html
@@ -127,10 +127,13 @@
-Generated on Mon Feb 24 2014 11:18:03 for pyrax by
+Generated on Wed Mar 12 2014 16:01:48 for pyrax by 1.7.6.1
diff --git a/docs/html/functions_0x63.html b/docs/html/functions_0x63.html
index 7fc003cc..c5341643 100644
--- a/docs/html/functions_0x63.html
+++ b/docs/html/functions_0x63.html
@@ -163,6 +163,12 @@
-Generated on Mon Feb 24 2014 11:18:03 for pyrax by
+Generated on Wed Mar 12 2014 16:01:48 for pyrax by 1.7.6.1
diff --git a/docs/html/functions_0x64.html b/docs/html/functions_0x64.html
index 5df4125b..681e74a0 100644
--- a/docs/html/functions_0x64.html
+++ b/docs/html/functions_0x64.html
@@ -203,9 +203,18 @@
-Generated on Mon Feb 24 2014 11:18:03 for pyrax by
+Generated on Wed Mar 12 2014 16:01:49 for pyrax by 1.7.6.1
diff --git a/docs/html/functions_0x65.html b/docs/html/functions_0x65.html
index 483752e0..fd788d1e 100644
--- a/docs/html/functions_0x65.html
+++ b/docs/html/functions_0x65.html
@@ -152,18 +152,21 @@
-Generated on Mon Feb 24 2014 11:18:03 for pyrax by
+Generated on Wed Mar 12 2014 16:01:49 for pyrax by 1.7.6.1
diff --git a/docs/html/functions_0x67.html b/docs/html/functions_0x67.html
index c56d96a3..9a3814c3 100644
--- a/docs/html/functions_0x67.html
+++ b/docs/html/functions_0x67.html
@@ -266,6 +266,27 @@
-Generated on Mon Feb 24 2014 11:18:03 for pyrax by
+Generated on Wed Mar 12 2014 16:01:49 for pyrax by 1.7.6.1
diff --git a/docs/html/functions_0x68.html b/docs/html/functions_0x68.html
index 95265d68..511dd091 100644
--- a/docs/html/functions_0x68.html
+++ b/docs/html/functions_0x68.html
@@ -150,12 +150,12 @@
-Generated on Mon Feb 24 2014 11:18:03 for pyrax by
+Generated on Wed Mar 12 2014 16:01:49 for pyrax by 1.7.6.1
diff --git a/docs/html/functions_0x69.html b/docs/html/functions_0x69.html
index 75b13607..a0f20c2e 100644
--- a/docs/html/functions_0x69.html
+++ b/docs/html/functions_0x69.html
@@ -122,39 +122,63 @@
-Generated on Mon Feb 24 2014 11:18:03 for pyrax by
+Generated on Wed Mar 12 2014 16:01:49 for pyrax by 1.7.6.1
diff --git a/docs/html/functions_0x6c.html b/docs/html/functions_0x6c.html
index 8e0f918a..5262616c 100644
--- a/docs/html/functions_0x6c.html
+++ b/docs/html/functions_0x6c.html
@@ -126,8 +126,10 @@
-Generated on Mon Feb 24 2014 11:18:03 for pyrax by
+Generated on Wed Mar 12 2014 16:01:49 for pyrax by 1.7.6.1
diff --git a/docs/html/functions_0x6e.html b/docs/html/functions_0x6e.html
index 6967dd0c..a8dffb17 100644
--- a/docs/html/functions_0x6e.html
+++ b/docs/html/functions_0x6e.html
@@ -122,10 +122,10 @@
-Generated on Mon Feb 24 2014 11:18:03 for pyrax by
+Generated on Wed Mar 12 2014 16:01:49 for pyrax by 1.7.6.1
diff --git a/docs/html/functions_0x70.html b/docs/html/functions_0x70.html
index f9893373..7cea3513 100644
--- a/docs/html/functions_0x70.html
+++ b/docs/html/functions_0x70.html
@@ -139,9 +139,10 @@
-Generated on Mon Feb 24 2014 11:18:03 for pyrax by
+Generated on Wed Mar 12 2014 16:01:49 for pyrax by 1.7.6.1
diff --git a/docs/html/functions_0x72.html b/docs/html/functions_0x72.html
index c8a3024f..358538ab 100644
--- a/docs/html/functions_0x72.html
+++ b/docs/html/functions_0x72.html
@@ -200,11 +200,12 @@
-Generated on Mon Feb 24 2014 11:18:03 for pyrax by
+Generated on Wed Mar 12 2014 16:01:49 for pyrax by 1.7.6.1
diff --git a/docs/html/functions_0x75.html b/docs/html/functions_0x75.html
index 22f7610a..75f188e1 100644
--- a/docs/html/functions_0x75.html
+++ b/docs/html/functions_0x75.html
@@ -130,8 +130,11 @@
-Generated on Mon Feb 24 2014 11:18:03 for pyrax by
+Generated on Wed Mar 12 2014 16:01:49 for pyrax by 1.7.6.1
diff --git a/docs/html/functions_func.html b/docs/html/functions_func.html
index 32344e94..cbdf3c76 100644
--- a/docs/html/functions_func.html
+++ b/docs/html/functions_func.html
@@ -139,9 +139,15 @@
-Generated on Mon Feb 24 2014 11:18:03 for pyrax by
+Generated on Wed Mar 12 2014 16:01:49 for pyrax by 1.7.6.1
diff --git a/docs/html/functions_func_0x61.html b/docs/html/functions_func_0x61.html
index 29052a45..4b93699a 100644
--- a/docs/html/functions_func_0x61.html
+++ b/docs/html/functions_func_0x61.html
@@ -118,15 +118,18 @@
-Generated on Mon Feb 24 2014 11:18:03 for pyrax by
+Generated on Wed Mar 12 2014 16:01:49 for pyrax by 1.7.6.1
diff --git a/docs/html/functions_func_0x63.html b/docs/html/functions_func_0x63.html
index 7fbf4e68..a7c0107d 100644
--- a/docs/html/functions_func_0x63.html
+++ b/docs/html/functions_func_0x63.html
@@ -126,9 +126,15 @@
-Generated on Mon Feb 24 2014 11:18:03 for pyrax by
+Generated on Wed Mar 12 2014 16:01:49 for pyrax by 1.7.6.1
diff --git a/docs/html/functions_func_0x64.html b/docs/html/functions_func_0x64.html
index b273be8d..102c36a4 100644
--- a/docs/html/functions_func_0x64.html
+++ b/docs/html/functions_func_0x64.html
@@ -194,30 +194,39 @@
-Generated on Mon Feb 24 2014 11:18:03 for pyrax by
+Generated on Wed Mar 12 2014 16:01:49 for pyrax by 1.7.6.1
diff --git a/docs/html/functions_func_0x65.html b/docs/html/functions_func_0x65.html
index bf0d0013..4d4c514a 100644
--- a/docs/html/functions_func_0x65.html
+++ b/docs/html/functions_func_0x65.html
@@ -125,16 +125,19 @@
-Generated on Mon Feb 24 2014 11:18:03 for pyrax by
+Generated on Wed Mar 12 2014 16:01:49 for pyrax by 1.7.6.1
diff --git a/docs/html/functions_func_0x67.html b/docs/html/functions_func_0x67.html
index 1acc7996..e2282ba0 100644
--- a/docs/html/functions_func_0x67.html
+++ b/docs/html/functions_func_0x67.html
@@ -254,6 +254,27 @@
-Generated on Mon Feb 24 2014 11:18:03 for pyrax by
+Generated on Wed Mar 12 2014 16:01:49 for pyrax by 1.7.6.1
diff --git a/docs/html/functions_func_0x69.html b/docs/html/functions_func_0x69.html
index e686103d..d2b7bd31 100644
--- a/docs/html/functions_func_0x69.html
+++ b/docs/html/functions_func_0x69.html
@@ -115,12 +115,34 @@
-Generated on Mon Feb 24 2014 11:18:03 for pyrax by
+Generated on Wed Mar 12 2014 16:01:49 for pyrax by 1.7.6.1
diff --git a/docs/html/functions_func_0x6c.html b/docs/html/functions_func_0x6c.html
index bfc577b0..73f72bf2 100644
--- a/docs/html/functions_func_0x6c.html
+++ b/docs/html/functions_func_0x6c.html
@@ -122,17 +122,23 @@
-Generated on Mon Feb 24 2014 11:18:03 for pyrax by
+Generated on Wed Mar 12 2014 16:01:49 for pyrax by 1.7.6.1
diff --git a/docs/html/functions_func_0x75.html b/docs/html/functions_func_0x75.html
index 7d8fbc77..e37a4162 100644
--- a/docs/html/functions_func_0x75.html
+++ b/docs/html/functions_func_0x75.html
@@ -128,8 +128,11 @@
-Generated on Mon Feb 24 2014 11:18:03 for pyrax by
+Generated on Wed Mar 12 2014 16:01:49 for pyrax by 1.7.6.1
diff --git a/docs/html/functions_vars_0x69.html b/docs/html/functions_vars_0x69.html
index e0a5b8a5..8ac7e02c 100644
--- a/docs/html/functions_vars_0x69.html
+++ b/docs/html/functions_vars_0x69.html
@@ -124,6 +124,9 @@
-Generated on Mon Feb 24 2014 11:18:03 for pyrax by
+Generated on Wed Mar 12 2014 16:01:49 for pyrax by 1.7.6.1
diff --git a/docs/html/functions_vars_0x6e.html b/docs/html/functions_vars_0x6e.html
index 21dd62f9..aa0732ec 100644
--- a/docs/html/functions_vars_0x6e.html
+++ b/docs/html/functions_vars_0x6e.html
@@ -122,9 +122,10 @@
-Generated on Mon Feb 24 2014 11:18:03 for pyrax by
+Generated on Wed Mar 12 2014 16:01:49 for pyrax by 1.7.6.1
diff --git a/docs/html/functions_vars_0x70.html b/docs/html/functions_vars_0x70.html
index dcc7d05d..a6708956 100644
--- a/docs/html/functions_vars_0x70.html
+++ b/docs/html/functions_vars_0x70.html
@@ -132,8 +132,9 @@
-Generated on Mon Feb 24 2014 11:18:03 for pyrax by
+Generated on Wed Mar 12 2014 16:01:49 for pyrax by 1.7.6.1
diff --git a/docs/html/functions_vars_0x72.html b/docs/html/functions_vars_0x72.html
index 84f76c57..1c592b33 100644
--- a/docs/html/functions_vars_0x72.html
+++ b/docs/html/functions_vars_0x72.html
@@ -137,11 +137,12 @@
-Generated on Mon Feb 24 2014 11:18:03 for pyrax by
+Generated on Wed Mar 12 2014 16:01:49 for pyrax by 1.7.6.1
diff --git a/docs/html/functions_vars_0x75.html b/docs/html/functions_vars_0x75.html
index 2224539d..5e4167ad 100644
--- a/docs/html/functions_vars_0x75.html
+++ b/docs/html/functions_vars_0x75.html
@@ -132,10 +132,8 @@
-Generated on Mon Feb 24 2014 11:18:03 for pyrax by
+Generated on Wed Mar 12 2014 16:01:49 for pyrax by 1.7.6.1
diff --git a/docs/html/hierarchy.html b/docs/html/hierarchy.html
index 73300a10..da59da44 100644
--- a/docs/html/hierarchy.html
+++ b/docs/html/hierarchy.html
@@ -122,6 +122,10 @@
-Generated on Mon Feb 24 2014 11:18:02 for pyrax by
+Generated on Wed Mar 12 2014 16:01:48 for pyrax by 1.7.6.1
diff --git a/docs/html/namespacemembers_func.html b/docs/html/namespacemembers_func.html
index 9888e297..bee0f820 100644
--- a/docs/html/namespacemembers_func.html
+++ b/docs/html/namespacemembers_func.html
@@ -85,6 +85,7 @@
-Generated on Mon Feb 24 2014 11:18:02 for pyrax by
+Generated on Wed Mar 12 2014 16:01:48 for pyrax by 1.7.6.1
diff --git a/docs/html/namespacemembers_vars.html b/docs/html/namespacemembers_vars.html
index ce39e784..f2420bb7 100644
--- a/docs/html/namespacemembers_vars.html
+++ b/docs/html/namespacemembers_vars.html
@@ -216,6 +216,9 @@
-Generated on Mon Feb 24 2014 11:18:02 for pyrax by
+Generated on Wed Mar 12 2014 16:01:48 for pyrax by 1.7.6.1
diff --git a/docs/html/namespacepyrax.html b/docs/html/namespacepyrax.html
index 672a1c45..3065329b 100644
--- a/docs/html/namespacepyrax.html
+++ b/docs/html/namespacepyrax.html
@@ -101,6 +101,7 @@
@@ -1222,7 +1269,7 @@
-Generated on Mon Feb 24 2014 11:17:57 for pyrax by
+Generated on Wed Mar 12 2014 16:01:43 for pyrax by 1.7.6.1
diff --git a/docs/html/namespacepyrax_1_1exceptions.html b/docs/html/namespacepyrax_1_1exceptions.html
index 10ca8358..2fcb3ba6 100644
--- a/docs/html/namespacepyrax_1_1exceptions.html
+++ b/docs/html/namespacepyrax_1_1exceptions.html
@@ -131,7 +131,6 @@
@@ -326,7 +329,7 @@
-Generated on Mon Feb 24 2014 11:17:58 for pyrax by
+Generated on Wed Mar 12 2014 16:01:44 for pyrax by 1.7.6.1
diff --git a/docs/html/namespacepyrax_1_1fakes.html b/docs/html/namespacepyrax_1_1fakes.html
index 90bdbe31..2910f035 100644
--- a/docs/html/namespacepyrax_1_1fakes.html
+++ b/docs/html/namespacepyrax_1_1fakes.html
@@ -160,6 +160,11 @@
Given a set of optional parameter names, constructs a dictionary with the parameter name as the key, and the value for that key in the local_dict as the value, for all non-None values.
For parameters that can take either a single string or a list of strings, this function will ensure that the result is a list containing the passed values.
Takes a dictionary and uses it to create a query string.
+
@@ -900,7 +921,7 @@
-Generated on Thu Oct 24 2013 09:26:06 for pyrax by
+Generated on Wed Mar 12 2014 16:01:48 for pyrax by 1.7.6.1
diff --git a/docs/html/namespacepyrax_1_1version.html b/docs/html/namespacepyrax_1_1version.html
index 347a890f..adfaf1d7 100644
--- a/docs/html/namespacepyrax_1_1version.html
+++ b/docs/html/namespacepyrax_1_1version.html
@@ -105,7 +105,7 @@
@@ -139,7 +139,7 @@
-Generated on Mon Feb 24 2014 11:18:02 for pyrax by
+Generated on Wed Mar 12 2014 16:01:48 for pyrax by 1.7.6.1
diff --git a/docs/html/namespaces.html b/docs/html/namespaces.html
index a564d286..60746549 100644
--- a/docs/html/namespaces.html
+++ b/docs/html/namespaces.html
@@ -101,6 +101,7 @@
Given a set of optional parameter names, constructs a dictionary with the parameter name as the key, and the value for that key in the local_dict as the value, for all non-None values.
@@ -168,7 +170,7 @@
-Generated on Thu Oct 24 2013 09:26:02 for pyrax by
+Generated on Wed Mar 12 2014 16:01:43 for pyrax by 1.7.6.1
diff --git a/docs/html/version_8py.html b/docs/html/version_8py.html
index 7734eb56..97d5f95f 100644
--- a/docs/html/version_8py.html
+++ b/docs/html/version_8py.html
@@ -88,7 +88,7 @@
@@ -108,7 +108,7 @@
-Generated on Mon Feb 24 2014 11:17:57 for pyrax by
+Generated on Wed Mar 12 2014 16:01:43 for pyrax by 1.7.6.1
diff --git a/docs/images.md b/docs/images.md
new file mode 100644
index 00000000..304bd716
--- /dev/null
+++ b/docs/images.md
@@ -0,0 +1,107 @@
+# Images
+
+## Basic Concepts
+The Images API allows you to do much more with your compute resources than simply create cloud servers. You can create snapshots of your servers in a particular state, and then share them with others. You can export images to a Cloud Files container, and then copy the image to another data center, from which you can then import it to create copies of compute resources. You can even copy your images to another OpenStack provider and import them there.
+
+There are two main types of images: **public** and **private**. Public images are those supplied by your cloud provider, and are available to everyone. Private images are those that you create in your own account by creating snapshots of your compute resources; these are only available to your account, or to any account with which you explicitly share them.
+
+
+## Using Images in pyrax
+Once you have authenticated, you can reference the Images service via `pyrax.images`. To make your coding easier, include the following line at the beginning of your code:
+
+ imgs = pyrax.images
+
+Then you can simply use the alias `imgs` to reference the service. All of the code samples in this document assume that `imgs` has been defined this way.
+
+
+## Listing Images
+To get a list of the images you have, run:
+
+ images = imgs.list()
+ print images
+
+This returns a list of Image objects that looks something like this:
+
+ [,
+ ,
+ ]
+
+The list that is returned is subject to the built-in limit of 25 images; you can use the pagination parameters (described below) to get more results, or, if you know you want the full listing, call:
+
+ all_images = imgs.list_all()
+
+
+### Filtering Image Listings
+The call to `list()` takes several optional parameters which are used to return just the images that meet the specified values. Here are the available parameters and their effects:
+
+Parameter | Effect
+-------- | -----
+**limit** | Restricts the number of Image objects returned. Fewer objects may be returned if there are not as many as the limit.
+**marker** | Used in pagination to determine where to start the next listing. It is the value of the `id` of the last image returned from the previous listing.
+**name** | Filters images whose name exactly matches this value. No wildcards can be used.
+**visibility** | Filters images on whether they are 'public' or 'private'.
+**member_status** | Filters images to only those that have members with the specified status; values can be 'accepted', 'pending', or 'rejected'. See the section on Sharing Images below.
+**owner** | Filters images to those shared with my account by the specified owner.
+**tag** | Filters images that contain the specified tag.
+**status** | Filter parameter that species the image status as 'queued', 'saving', 'active', 'killed', 'deleted', or 'pending_delete'.
+**size_min** | Filters images whose size **in bytes** is greater than or equal to this value.
+**size_max** | Filters images whose size **in bytes** is less than or equal to this value.
+**sort_key** | Images by default are returned in order of their **created_at** value. You can specifiy any other attribute of an image to control the sorting with this parameter.
+**sort_dir** | Sort direction. Valid values are 'asc' (ascending) and 'desc' (descending). The default is 'desc'.
+
+
+## Sharing an Image
+You share an image that you own by adding accounts other than your own to the image; these external accounts are referred to as _members_. Members are represented by the account number with which you want to share the image; in OpenStack terms, this is the **project_id** (formerly called _tenant_id_). To add a member whose project_id is '12345abc' to the image 'img', call:
+
+ imgs.add_image_member(img, "12345abc")
+
+In this call, 'img' can be either an Image object, or simply the `id` of the image. If 'img' is an Image object, you can call it directly:
+
+ img.add_member("12345abc")
+
+When you add a member to an image you own, they have access to the image and can create new compute resources from it, but it does not appear in their image listings. The member has a status of 'pending' until they either accept or reject the share. Once they accept, the image appears when they retrieve a list of available images.
+
+Note that the image owner cannot change the status of a member; that member with who the image is being shared must do so from their own account. In the event that someone has shared an image with you, you need to get the image ID from the owner. Once you have that, you then call:
+
+ imgs.update_image_member(img_id, status)
+
+where `img_id` is the ID of the image being shared, and `status` is either 'accepted' or 'rejected', depending on what you want to do. There is a third status option: 'pending' - this returns the image member to the state it was in when first shared.
+
+Once an image is shared with a member, they can create new servers with it, but they cannot update or delete it.
+
+If you no longer wish to share an image with a member, you can remove them by calling:
+
+ imgs.delete_image_member(img, project_id)
+ # -or-
+ img.delete_member(project_id)
+
+
+## Exporting an Image
+Exporting an image allows you to move that image across data centers, or even to other cloud providers. When an image is exported, a copy of that image in VHD format is created in a Cloud Files container of your choosing, and a task is created to monitor the progress of the export. To export an image, call:
+
+ task = imgs.export_task(img, cont)
+
+In this call, `img` is either an Image object, or the ID of the image to export, and 'cont' is either a pyrax.cloudfiles.Container object, or the name of the Cloud Files container into which the exported image is to be placed.
+
+Once you have the task, you may poll its status by calling the following:
+
+ task.reload()
+ print task.status
+
+The possible status values are:
+
+Status | Meaning
+------ | -------
+pending | The task is waiting to begin executing
+processing | The task is currently running
+success | The task completed successfully
+failure | The task failed. When this happens, the `message` attribute of the task contains the reason for the failure.
+
+## Importing an Image
+You may import images for your use b first uploading them to a container in your Cloud Files account. Once the image is there, you import it by calling:
+
+ task = imgs.import_task(img, cont[, img_format=None[, img_name=None]])
+
+You must supply the image and container. In this case, `img` is the name of the image file within the container, and `cont` is the container name. You may also specify the format of the image by including the `img_format` parameter, but you do not need to if the image is in VHD format (the default). The imported image is named the same as the file in the container unless you include a value in the `img_name` parameter.
+
+Like exporting, importing an image returns a task which you can poll to see the progress. The same statuses apply to imports as exports.
diff --git a/pyrax/__init__.py b/pyrax/__init__.py
index b91483a9..5459da0c 100755
--- a/pyrax/__init__.py
+++ b/pyrax/__init__.py
@@ -35,13 +35,14 @@
It also adds in CDN functionality that is Rackspace-specific.
"""
-import ConfigParser
from functools import wraps
import inspect
import logging
import os
import warnings
+from six.moves import configparser
+
# keyring is an optional import
try:
import keyring
@@ -52,10 +53,10 @@
# since importing the version info in setup.py tries to import this
# entire module.
try:
- from identity import *
+ from .identity import *
- import exceptions as exc
- import version
+ from . import exceptions as exc
+ from . import version
import cf_wrapper.client as _cf
from novaclient import exceptions as _cs_exceptions
@@ -70,6 +71,7 @@
from clouddns import CloudDNSClient
from cloudnetworks import CloudNetworkClient
from cloudmonitoring import CloudMonitorClient
+ from image import ImageClient
from queueing import QueueClient
except ImportError:
# See if this is the result of the importing of version.py in setup.py
@@ -92,6 +94,7 @@
cloud_networks = None
cloud_monitoring = None
autoscale = None
+images = None
queues = None
# Default region for all services. Can be individually overridden if needed
default_region = None
@@ -121,6 +124,7 @@
"compute:network": CloudNetworkClient,
"monitor": CloudMonitorClient,
"autoscale": AutoScaleClient,
+ "image": ImageClient,
"queues": QueueClient,
}
@@ -260,17 +264,17 @@ def read_config(self, config_file):
Parses the specified configuration file and stores the values. Raises
an InvalidConfigurationFile exception if the file is not well-formed.
"""
- cfg = ConfigParser.SafeConfigParser()
+ cfg = configparser.SafeConfigParser()
try:
cfg.read(config_file)
- except ConfigParser.MissingSectionHeaderError as e:
+ except configparser.MissingSectionHeaderError as e:
# The file exists, but doesn't have the correct format.
raise exc.InvalidConfigurationFile(e)
def safe_get(section, option, default=None):
try:
return cfg.get(section, option)
- except (ConfigParser.NoSectionError, ConfigParser.NoOptionError):
+ except (configparser.NoSectionError, configparser.NoOptionError):
return default
# A common mistake is including credentials in the config file. If any
@@ -559,7 +563,7 @@ def clear_credentials():
"""De-authenticate by clearing all the names back to None."""
global identity, regions, services, cloudservers, cloudfiles
global cloud_loadbalancers, cloud_databases, cloud_blockstorage, cloud_dns
- global cloud_networks, cloud_monitoring, autoscale, queues
+ global cloud_networks, cloud_monitoring, autoscale, images, queues
identity = None
regions = tuple()
services = tuple()
@@ -572,6 +576,7 @@ def clear_credentials():
cloud_networks = None
cloud_monitoring = None
autoscale = None
+ images = None
queues = None
@@ -590,7 +595,7 @@ def connect_to_services(region=None):
"""Establishes authenticated connections to the various cloud APIs."""
global cloudservers, cloudfiles, cloud_loadbalancers, cloud_databases
global cloud_blockstorage, cloud_dns, cloud_networks, cloud_monitoring
- global autoscale, queues
+ global autoscale, images, queues
cloudservers = connect_to_cloudservers(region=region)
cloudfiles = connect_to_cloudfiles(region=region)
cloud_loadbalancers = connect_to_cloud_loadbalancers(region=region)
@@ -600,6 +605,7 @@ def connect_to_services(region=None):
cloud_networks = connect_to_cloud_networks(region=region)
cloud_monitoring = connect_to_cloud_monitoring(region=region)
autoscale = connect_to_autoscale(region=region)
+ images = connect_to_images(region=region)
queues = connect_to_queues(region=region)
@@ -758,6 +764,12 @@ def connect_to_autoscale(region=None):
region=region)
+def connect_to_images(region=None, public=True):
+ """Creates a client for working with Images."""
+ return _create_client(ep_name="image", service_type="image",
+ region=region, public=public)
+
+
def connect_to_queues(region=None, public=True):
"""Creates a client for working with Queues."""
return _create_client(ep_name="queues", service_type="queues",
@@ -776,7 +788,7 @@ def set_http_debug(val):
identity.http_log_debug = val
for svc in (cloudservers, cloudfiles, cloud_loadbalancers,
cloud_blockstorage, cloud_databases, cloud_dns, cloud_networks,
- autoscale, queues):
+ autoscale, images, queues):
if svc is not None:
svc.http_log_debug = val
if not val:
@@ -794,7 +806,7 @@ def get_encoding():
# Read in the configuration file, if any
settings = Settings()
-config_file = os.path.expanduser("~/.pyrax.cfg")
+config_file = os.path.join(os.path.expanduser("~"), ".pyrax.cfg")
if os.path.exists(config_file):
settings.read_config(config_file)
debug = get_setting("http_debug") or False
diff --git a/pyrax/base_identity.py b/pyrax/base_identity.py
index 84d1b49c..49964e95 100644
--- a/pyrax/base_identity.py
+++ b/pyrax/base_identity.py
@@ -1,12 +1,15 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
-import ConfigParser
+from __future__ import print_function
+
import datetime
import json
import re
import requests
+from six.moves import configparser
+
import pyrax
import pyrax.exceptions as exc
from pyrax.resource import BaseResource
@@ -129,19 +132,19 @@ def set_credential_file(self, credential_file, region=None,
"""
self._creds_file = credential_file
- cfg = ConfigParser.SafeConfigParser()
+ cfg = configparser.SafeConfigParser()
try:
if not cfg.read(credential_file):
# If the specified file does not exist, the parser will
# return an empty list
raise exc.FileNotFound("The specified credential file '%s' "
"does not exist" % credential_file)
- except ConfigParser.MissingSectionHeaderError as e:
+ except configparser.MissingSectionHeaderError as e:
# The file exists, but doesn't have the correct format.
raise exc.InvalidCredentialFile(e)
try:
self._read_credential_file(cfg)
- except (ConfigParser.NoSectionError, ConfigParser.NoOptionError) as e:
+ except (configparser.NoSectionError, configparser.NoOptionError) as e:
raise exc.InvalidCredentialFile(e)
if region:
self.region = region
@@ -254,11 +257,11 @@ def _call(self, mthd, uri, admin, data, headers, std_headers):
hdrs.update(headers)
jdata = json.dumps(data) if data else None
if self.http_log_debug:
- print "REQ:", mthd.func_name.upper(), uri
- print "HDRS:", hdrs
+ print("REQ:", mthd.func_name.upper(), uri)
+ print("HDRS:", hdrs)
if data:
- print "DATA", jdata
- print
+ print("DATA", jdata)
+ print()
return mthd(uri, data=jdata, headers=hdrs, verify=self.verify_ssl)
diff --git a/pyrax/cf_wrapper/client.py b/pyrax/cf_wrapper/client.py
index ce2a8e5f..a720aac7 100644
--- a/pyrax/cf_wrapper/client.py
+++ b/pyrax/cf_wrapper/client.py
@@ -22,6 +22,8 @@
import uuid
import mimetypes
+import six
+
from swiftclient import client as _swift_client
import pyrax
from pyrax.cf_wrapper.container import Container
@@ -71,31 +73,30 @@ def _wrapped(self, *args, **kwargs):
ret = fnc(self, *args, **kwargs)
return ret
except _swift_client.ClientException as e:
- if attempts < AUTH_ATTEMPTS:
- # Assume it is an auth failure. Re-auth and retry.
- ### NOTE: This is a hack to get around an apparent bug
- ### in python-swiftclient when using Rackspace auth.
- pyrax.authenticate(connect=False)
- if pyrax.identity.authenticated:
- pyrax.plug_hole_in_swiftclient_auth(self, clt_url)
- continue
str_error = "%s" % e
- bad_container = no_such_container_pattern.search(str_error)
- if bad_container:
- raise exc.NoSuchContainer("Container '%s' doesn't exist" %
- bad_container.groups()[0])
- bad_object = no_such_object_pattern.search(str_error)
- if bad_object:
- raise exc.NoSuchObject("Object '%s' doesn't exist" %
- bad_object.groups()[0])
+ if e.http_status == 401:
+ if attempts < AUTH_ATTEMPTS:
+ # Assume it is an auth failure. Re-auth and retry.
+ ### NOTE: This is a hack to get around an apparent bug
+ ### in python-swiftclient when using Rackspace auth.
+ pyrax.authenticate(connect=False)
+ if pyrax.identity.authenticated:
+ pyrax.plug_hole_in_swiftclient_auth(self, clt_url)
+ continue
+ elif e.http_status == 404:
+ bad_container = no_such_container_pattern.search(str_error)
+ if bad_container:
+ raise exc.NoSuchContainer("Container '%s' doesn't exist"
+ % bad_container.groups()[0])
+ bad_object = no_such_object_pattern.search(str_error)
+ if bad_object:
+ raise exc.NoSuchObject("Object '%s' doesn't exist" %
+ bad_object.groups()[0])
failed_upload = etag_failed_pattern.search(str_error)
if failed_upload:
cont, fname = failed_upload.groups()
raise exc.UploadFailed("Upload of file '%(fname)s' to "
"container '%(cont)s' failed." % locals())
- if e.http_status == 404:
- raise exc.NoSuchObject("The requested object/container "
- "does not exist.")
# Not handled; re-raise
raise
return _wrapped
@@ -205,7 +206,7 @@ def _massage_metakeys(self, dct, prfx):
def _resolve_name(self, val):
- return val if isinstance(val, basestring) else val.name
+ return val if isinstance(val, six.string_types) else val.name
@handle_swiftclient_exception
@@ -314,7 +315,7 @@ def get_temp_url(self, container, obj, seconds, method="GET", key=None,
path_parts = (conn_url[v1pos:], cname, oname)
cleaned = (part.strip("/\\") for part in path_parts)
pth = "/%s" % "/".join(cleaned)
- if isinstance(pth, unicode):
+ if isinstance(pth, six.text_type):
pth = pth.encode(pyrax.get_encoding())
expires = int(time.time() + int(seconds))
hmac_body = "%s\n%s\n%s" % (mod_method, expires, pth)
@@ -749,7 +750,7 @@ def get_file_size(fileobj):
return total_size
def upload(fileobj, content_type, etag, headers):
- if isinstance(fileobj, basestring):
+ if isinstance(fileobj, six.string_types):
# This is an empty directory file
fsize = 0
else:
@@ -768,7 +769,7 @@ def upload(fileobj, content_type, etag, headers):
digits = int(math.log10(num_segments)) + 1
# NOTE: This could be greatly improved with threading or other
# async design.
- for segment in xrange(num_segments):
+ for segment in six.moves.range(num_segments):
sequence = str(segment + 1).zfill(digits)
seg_name = "%s.%s" % (obj_name, sequence)
with utils.SelfDeletingTempfile() as tmpname:
@@ -787,7 +788,7 @@ def upload(fileobj, content_type, etag, headers):
contents=None, headers=headers,
response_dict=extra_info)
- ispath = isinstance(file_or_path, basestring)
+ ispath = isinstance(file_or_path, six.string_types)
if ispath:
# Make sure it exists
if not os.path.exists(file_or_path):
@@ -1413,7 +1414,7 @@ def cdn_request(self, method, path=[], data="", hdrs=None):
Taken directly from the cloudfiles library and modified for use here.
"""
def quote(val):
- if isinstance(val, unicode):
+ if isinstance(val, six.text_type):
val = val.encode("utf-8")
return urllib.quote(val)
diff --git a/pyrax/cf_wrapper/storage_object.py b/pyrax/cf_wrapper/storage_object.py
index 7be6a973..1eee3317 100644
--- a/pyrax/cf_wrapper/storage_object.py
+++ b/pyrax/cf_wrapper/storage_object.py
@@ -17,6 +17,7 @@
# License for the specific language governing permissions and limitations
# under the License.
+import six
class StorageObject(object):
"""Represents a CloudFiles storage object."""
@@ -27,7 +28,7 @@ def __init__(self, client, container, name=None, total_bytes=None,
passing the dict that is returned by swiftclient.
"""
self.client = client
- if isinstance(container, basestring):
+ if isinstance(container, six.string_types):
self.container = self.client.get_container(container)
else:
self.container = container
diff --git a/pyrax/client.py b/pyrax/client.py
index 8d109f4c..b66996ba 100644
--- a/pyrax/client.py
+++ b/pyrax/client.py
@@ -154,7 +154,7 @@ def http_log_req(self, args, kwargs):
return
string_parts = ["curl -i"]
for element in args:
- if element in ("GET", "POST", "PUT", "DELETE", "HEAD"):
+ if element in ("GET", "POST", "PUT", "DELETE", "HEAD", "PATCH"):
string_parts.append(" -X %s" % element)
else:
string_parts.append(" %s" % element)
@@ -199,7 +199,8 @@ def request(self, *args, **kwargs):
kwargs["headers"]["User-Agent"] = self.user_agent
kwargs["headers"]["Accept"] = "application/json"
if "body" in kwargs:
- kwargs["headers"]["Content-Type"] = "application/json"
+ if not kwargs["headers"].get("Content-Type"):
+ kwargs["headers"]["Content-Type"] = "application/json"
kwargs["body"] = json.dumps(kwargs["body"])
# Allow subclasses to add their own headers
self._add_custom_headers(kwargs["headers"])
diff --git a/pyrax/cloudblockstorage.py b/pyrax/cloudblockstorage.py
index d2798173..8fd02584 100644
--- a/pyrax/cloudblockstorage.py
+++ b/pyrax/cloudblockstorage.py
@@ -20,6 +20,8 @@
from functools import wraps
import time
+import six
+
import pyrax
from pyrax.client import BaseClient
import pyrax.exceptions as exc
@@ -34,12 +36,12 @@
def _resolve_id(val):
"""Takes an object or an ID and returns the ID."""
- return val if isinstance(val, basestring) else val.id
+ return val if isinstance(val, six.string_types) else val.id
def _resolve_name(val):
"""Takes an object or a name and returns the name."""
- return val if isinstance(val, basestring) else val.name
+ return val if isinstance(val, six.string_types) else val.name
def assure_volume(fnc):
diff --git a/pyrax/clouddatabases.py b/pyrax/clouddatabases.py
index 5771dac7..3acc781f 100644
--- a/pyrax/clouddatabases.py
+++ b/pyrax/clouddatabases.py
@@ -19,6 +19,8 @@
from functools import wraps
+import six
+
from pyrax.client import BaseClient
import pyrax.exceptions as exc
from pyrax.manager import BaseManager
@@ -418,7 +420,7 @@ def create_user(self, name, password, database_names, host=None):
if not isinstance(database_names, (list, tuple)):
database_names = [database_names]
# The API only accepts names, not DB objects
- database_names = [db if isinstance(db, basestring) else db.name
+ database_names = [db if isinstance(db, six.string_types) else db.name
for db in database_names]
self._user_manager.create(name=name, password=password,
database_names=database_names, host=host, return_none=True)
diff --git a/pyrax/clouddns.py b/pyrax/clouddns.py
index 7522cb23..f8260c2a 100644
--- a/pyrax/clouddns.py
+++ b/pyrax/clouddns.py
@@ -22,6 +22,8 @@
import re
import time
+import six
+
import pyrax
from pyrax.client import BaseClient
from pyrax.cloudloadbalancers import CloudLoadBalancer
@@ -432,7 +434,7 @@ def _retry_get(self, uri):
Handles GET calls to the Cloud DNS API in order to retry on empty
body responses.
"""
- for i in xrange(DEFAULT_RETRY):
+ for i in six.moves.range(DEFAULT_RETRY):
resp, body = self.api.method_get(uri)
if body:
return resp, body
@@ -1036,7 +1038,7 @@ def method_get(self, uri, **kwargs):
Overload the method_get function in order to retry on empty body
responses from the Cloud DNS API
"""
- for i in xrange(3):
+ for i in six.moves.range(3):
resp, body = super(CloudDNSClient, self).method_get(uri, **kwargs)
if body:
return resp, body
diff --git a/pyrax/cloudloadbalancers.py b/pyrax/cloudloadbalancers.py
index 99e3da1a..58164344 100644
--- a/pyrax/cloudloadbalancers.py
+++ b/pyrax/cloudloadbalancers.py
@@ -19,6 +19,8 @@
from functools import wraps
+import six
+
import pyrax
from pyrax.client import BaseClient
import pyrax.exceptions as exc
@@ -396,7 +398,7 @@ def _get_session_persistence(self):
def _set_session_persistence(self, val):
if val:
- if not isinstance(val, basestring) or (val.upper() not in
+ if not isinstance(val, six.string_types) or (val.upper() not in
("HTTP_COOKIE", "SOURCE_IP")):
raise exc.InvalidSessionPersistenceType("Session Persistence "
"must be one of 'HTTP_COOKIE' or 'SOURCE_IP'. '%s' is "
diff --git a/pyrax/exceptions.py b/pyrax/exceptions.py
index 646557ac..af812391 100644
--- a/pyrax/exceptions.py
+++ b/pyrax/exceptions.py
@@ -95,9 +95,6 @@ class FileNotFound(PyraxException):
class FolderNotFound(PyraxException):
pass
-class InvalidEmail(PyraxException):
- pass
-
class KeyringModuleNotInstalled(PyraxException):
pass
@@ -125,12 +122,24 @@ class InvalidDateTimeString(PyraxException):
class InvalidDeviceType(PyraxException):
pass
+class InvalidEmail(PyraxException):
+ pass
+
+class InvalidImageMember(PyraxException):
+ pass
+
+class InvalidImageMemberStatus(PyraxException):
+ pass
+
class InvalidLoadBalancer(PyraxException):
pass
class InvalidLoadBalancerParameters(PyraxException):
pass
+class InvalidImageMemberStatus(PyraxException):
+ pass
+
class InvalidMonitoringCheckDetails(PyraxException):
pass
@@ -302,6 +311,9 @@ class UnattachedVirtualIP(PyraxException):
class UnicodePathError(PyraxException):
pass
+class UnsharableImage(PyraxException):
+ pass
+
class UploadFailed(PyraxException):
pass
diff --git a/pyrax/fakes.py b/pyrax/fakes.py
index 73ca1d06..c82b62e4 100644
--- a/pyrax/fakes.py
+++ b/pyrax/fakes.py
@@ -44,6 +44,11 @@
from pyrax.cloudmonitoring import CloudMonitorEntity
from pyrax.cloudmonitoring import CloudMonitorCheck
from pyrax.cloudmonitoring import CloudMonitorNotification
+from pyrax.image import Image
+from pyrax.image import ImageClient
+from pyrax.image import ImageManager
+from pyrax.image import ImageMemberManager
+from pyrax.image import ImageTagManager
from pyrax.queueing import Queue
from pyrax.queueing import QueueClaim
from pyrax.queueing import QueueMessage
@@ -553,6 +558,49 @@ def __init__(self, api=None, *args, **kwargs):
self.id = utils.random_ascii()
+class FakeImage(Image):
+ def __init__(self, *args, **kwargs):
+ info = kwargs.pop("info", {"fake": "fake"})
+ info["name"] = utils.random_unicode()
+ info["id"] = utils.random_unicode()
+ mgr = kwargs.pop("manager", FakeImageManager())
+ kwargs["member_manager_class"] = FakeImageMemberManager
+ kwargs["tag_manager_class"] = FakeImageTagManager
+ super(FakeImage, self).__init__(mgr, info, *args, **kwargs)
+
+
+class FakeImageClient(ImageClient):
+ def __init__(self, *args, **kwargs):
+ super(FakeImageClient, self).__init__("fakeuser",
+ "fakepassword", *args, **kwargs)
+
+
+class FakeImageMemberManager(ImageMemberManager):
+ def __init__(self, api=None, *args, **kwargs):
+ if api is None:
+ api = FakeImageClient()
+ super(FakeImageMemberManager, self).__init__(api, *args, **kwargs)
+ self.id = utils.random_ascii()
+
+
+class FakeImageTagManager(ImageTagManager):
+ def __init__(self, api=None, *args, **kwargs):
+ if api is None:
+ api = FakeImageClient()
+ super(FakeImageTagManager, self).__init__(api, *args, **kwargs)
+ self.id = utils.random_ascii()
+
+
+class FakeImageManager(ImageManager):
+ def __init__(self, api=None, *args, **kwargs):
+ if api is None:
+ api = FakeImageClient()
+ super(FakeImageManager, self).__init__(api, *args, **kwargs)
+ self.plural_response_key = "images"
+ self.resource_class = FakeImage
+ self.id = utils.random_ascii()
+
+
class FakeIdentity(RaxIdentity):
"""Class that returns canned authentication responses."""
def __init__(self, *args, **kwargs):
diff --git a/pyrax/identity/rax_identity.py b/pyrax/identity/rax_identity.py
index 1dac6c9e..a2cea2a0 100644
--- a/pyrax/identity/rax_identity.py
+++ b/pyrax/identity/rax_identity.py
@@ -1,7 +1,7 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
-import ConfigParser
+from six.moves import configparser
from pyrax.base_identity import BaseAuth
from pyrax.base_identity import User
@@ -31,7 +31,7 @@ def _read_credential_file(self, cfg):
self.username = cfg.get("rackspace_cloud", "username")
try:
self.password = cfg.get("rackspace_cloud", "api_key", raw=True)
- except ConfigParser.NoOptionError as e:
+ except configparser.NoOptionError as e:
# Allow either the use of either 'api_key' or 'password'.
self.password = cfg.get("rackspace_cloud", "password", raw=True)
diff --git a/pyrax/image.py b/pyrax/image.py
new file mode 100644
index 00000000..810a4db4
--- /dev/null
+++ b/pyrax/image.py
@@ -0,0 +1,683 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+# Copyright 2014 Rackspace
+
+# All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+from functools import wraps
+
+import pyrax
+from pyrax.client import BaseClient
+import pyrax.exceptions as exc
+from pyrax.manager import BaseManager
+from pyrax.resource import BaseResource
+import pyrax.utils as utils
+
+
+DEFAULT_FORMAT = "vhd"
+
+
+def assure_image(fnc):
+ """
+ Converts a image ID passed as the 'image' parameter to a image object.
+ """
+ @wraps(fnc)
+ def _wrapped(self, img, *args, **kwargs):
+ if not isinstance(img, Image):
+ # Must be the ID
+ img = self._manager.get(img)
+ return fnc(self, img, *args, **kwargs)
+ return _wrapped
+
+
+
+class Image(BaseResource):
+ """
+ This class represents an Image.
+ """
+ def __init__(self, manager, info, key=None, loaded=False,
+ member_manager_class=None, tag_manager_class=None):
+ super(Image, self).__init__(manager, info, key=key, loaded=loaded)
+ member_manager_class = member_manager_class or ImageMemberManager
+ tag_manager_class = tag_manager_class or ImageTagManager
+ self._member_manager = member_manager_class(self.manager.api,
+ resource_class=ImageMember, response_key="",
+ plural_response_key="members", uri_base="images/%s/members" %
+ self.id)
+ self._tag_manager = tag_manager_class(self.manager.api,
+ resource_class=ImageTag, response_key="",
+ plural_response_key="tags", uri_base="images/%s/tags" %
+ self.id)
+ self._non_display = [
+ "com.rackspace__1__build_core",
+ "com.rackspace__1__build_managed",
+ "com.rackspace__1__build_rackconnect",
+ "com.rackspace__1__options",
+ "com.rackspace__1__platform_target",
+ "com.rackspace__1__release_build_date",
+ "com.rackspace__1__release_id",
+ "com.rackspace__1__release_version",
+ "com.rackspace__1__source",
+ "com.rackspace__1__visible_core",
+ "com.rackspace__1__visible_managed",
+ "com.rackspace__1__visible_rackconnect",
+ "file",
+ "instance_type_ephemeral_gb",
+ "instance_type_flavorid",
+ "instance_type_id",
+ "instance_type_memory_mb",
+ "instance_type_name",
+ "instance_type_root_gb",
+ "instance_type_rxtx_factor",
+ "instance_type_swap",
+ "instance_type_vcpu_weight",
+ "instance_type_vcpus",
+ "instance_uuid",
+ "org.openstack__1__architecture",
+ "org.openstack__1__os_distro",
+ "org.openstack__1__os_version",
+ "rax_activation_profile",
+ "rax_managed",
+ "rax_options",
+ "schema",
+ "self",
+ ]
+
+
+ def update(self, value_dict):
+ """
+ Accepts a and dictionary of key/value pairs, where the key is an
+ attribute of the image, and the value is the desired new value for that
+ image.
+ """
+ return self.manager.update(self, value_dict)
+
+
+ def change_name(self, newname):
+ """
+ Image name can be changed via the update() method. This is simply a
+ convenience method.
+ """
+ return self.update({"name": newname})
+
+
+ def list_members(self):
+ """
+ Returns a list of all Members for this image.
+ """
+ return self._member_manager.list()
+
+
+ def get_member(self, member):
+ """
+ Returns the ImageMember object representing the specified member
+ """
+ return self._member_manager.get(member)
+
+
+ def add_member(self, project_id):
+ """
+ Adds the project (tenant) represented by the project_id as a member of
+ this image.
+ """
+ return self._member_manager.create(name=None, project_id=project_id)
+
+
+ def delete_member(self, project_id):
+ """
+ Removes the project (tenant) represented by the project_id as a member
+ of this image.
+ """
+ return self._member_manager.delete(project_id)
+
+
+ def add_tag(self, tag):
+ """
+ Adds the tag to this image.
+ """
+ return self._tag_manager.add(tag)
+
+
+ def delete_tag(self, tag):
+ """
+ Deletes the tag from this image.
+ """
+ return self._tag_manager.delete(tag)
+
+
+
+class ImageMember(BaseResource):
+ """
+ This class represents a member (user) of an Image.
+ """
+ @property
+ def id(self):
+ return self.member_id
+
+
+
+class ImageTag(BaseResource):
+ """
+ This class represents a tag for an Image.
+ """
+ pass
+
+
+
+class ImageTask(BaseResource):
+ """
+ This class represents a ImageTask.
+ """
+ pass
+
+
+
+class ImageManager(BaseManager):
+ """
+ Manager class for an Image.
+ """
+ def _create_body(self, name, metadata=None):
+ """
+ Used to create the dict required to create a new queue
+ """
+ if metadata is None:
+ body = {}
+ else:
+ body = {"metadata": metadata}
+ return body
+
+
+ def list(self, limit=None, marker=None, name=None, visibility=None,
+ member_status=None, owner=None, tag=None, status=None,
+ size_min=None, size_max=None, sort_key=None, sort_dir=None,
+ return_raw=False):
+ """
+ Returns a list of resource objects. Pagination is supported through the
+ optional 'marker' and 'limit' parameters. Filtering the returned value
+ is possible by specifying values for any of the other parameters.
+ """
+ uri = "/%s" % self.uri_base
+ qs = utils.dict_to_qs(dict(limit=limit, marker=marker, name=name,
+ visibility=visibility, member_status=member_status,
+ owner=owner, tag=tag, status=status, size_min=size_min,
+ size_max=size_max, sort_key=sort_key, sort_dir=sort_dir))
+ if qs:
+ uri = "%s?%s" % (uri, qs)
+ return self._list(uri, return_raw=return_raw)
+
+
+ def list_all(self, name=None, visibility=None, member_status=None,
+ owner=None, tag=None, status=None, size_min=None, size_max=None,
+ sort_key=None, sort_dir=None):
+ """
+ Returns all of the images in one call, rather than in paginated batches.
+ """
+
+ def strip_version(uri):
+ """
+ The 'next' uri contains a redundant version number. We need to
+ strip it to use in the method_get() call.
+ """
+ pos = uri.find("/images")
+ return uri[pos:]
+
+ obj_class = self.resource_class
+ resp, resp_body = self.list(name=name, visibility=visibility,
+ member_status=member_status, owner=owner, tag=tag,
+ status=status, size_min=size_min, size_max=size_max,
+ sort_key=sort_key, sort_dir=sort_dir, return_raw=True)
+ data = resp_body.get(self.plural_response_key, resp_body)
+ next_uri = strip_version(resp_body.get("next", ""))
+ ret = [obj_class(manager=self, info=res) for res in data if res]
+ while next_uri:
+ resp, resp_body = self.api.method_get(next_uri)
+ data = resp_body.get(self.plural_response_key, resp_body)
+ next_uri = strip_version(resp_body.get("next", ""))
+ ret.extend([obj_class(manager=self, info=res)
+ for res in data if res])
+ return ret
+
+
+ def update(self, img, value_dict):
+ """
+ Accepts an image reference (object or ID) and dictionary of key/value
+ pairs, where the key is an attribute of the image, and the value is the
+ desired new value for that image.
+
+ NOTE: There is a bug in Glance where the 'add' operation returns a 409
+ if the property already exists, which conflicts with the spec. So to
+ get around this a fresh copy of the image must be retrieved, and the
+ value of 'op' must be determined based on whether this attribute exists
+ or not.
+ """
+ img = self.get(img)
+ uri = "/%s/%s" % (self.uri_base, utils.get_id(img))
+ body = []
+ for key, val in value_dict.items():
+ op = "replace" if key in img.__dict__ else "add"
+ body.append({"op": op,
+ "path": "/%s" % key,
+ "value": val})
+ headers = {"Content-Type":
+ "application/openstack-images-v2.1-json-patch"}
+ resp, resp_body = self.api.method_patch(uri, body=body, headers=headers)
+
+
+ def update_image_member(self, img_id, status):
+ """
+ Updates the image whose ID is given with the status specified. This
+ must be called by the user whose project_id is in the members for the
+ image. If called by the owner of the image, an InvalidImageMember
+ exception will be raised.
+
+ Valid values for 'status' include:
+ pending
+ accepted
+ rejected
+ Any other value will result in an InvalidImageMemberStatus exception
+ being raised.
+ """
+ if status not in ("pending", "accepted", "rejected"):
+ raise exc.InvalidImageMemberStatus("The status value must be one "
+ "of 'accepted', 'rejected', or 'pending'. Received: '%s'" %
+ status)
+ project_id = pyrax.identity.tenant_id
+ uri = "/%s/%s/members/%s" % (self.uri_base, img_id, project_id)
+ body = {"status": status}
+ try:
+ resp, resp_body = self.api.method_put(uri, body=body)
+ except exc.NotFound as e:
+ raise exc.InvalidImageMember("The update member request could not "
+ "be completed. No member request for that image was found.")
+
+
+
+class ImageMemberManager(BaseManager):
+ """
+ Manager class for members (users) of an Image.
+ """
+ def _create_body(self, name, project_id):
+ """
+ Used to create the dict required to add a member to this image.
+ """
+ body = {"member": project_id}
+ return body
+
+
+ def create(self, name, *args, **kwargs):
+ """
+ Need to wrap the default call to handle exceptions.
+ """
+ try:
+ return super(ImageMemberManager, self).create(name, *args, **kwargs)
+ except Exception as e:
+ if e.http_status == 403:
+ raise exc.UnsharableImage("You cannot share a public image.")
+ else:
+ raise
+
+
+
+class ImageTagManager(BaseManager):
+ """
+ Manager class for Image tags.
+ """
+ def _create_body(self, name):
+ """
+ Not used; the add() method is used with a PUT request.
+ """
+ return {}
+
+
+ def add(self, tag):
+ """
+ """
+ uri = "/%s/%s" % (self.uri_base, tag)
+ resp, resp_body = self.api.method_put(uri)
+
+
+
+class ImageTasksManager(BaseManager):
+ """
+ Manager class for ImageTasks.
+ """
+ def _create_body(self, name, img=None, cont=None, img_format=None,
+ img_name=None):
+ """
+ Used to create a new task. Since tasks don't have names, the required
+ 'name' parameter is used for the type of task: 'import' or 'export'.
+ """
+ img = utils.get_id(img)
+ cont = utils.get_name(cont)
+ body = {"type": name}
+ if name == "export":
+ body["input"] = {
+ "image_uuid": img,
+ "receiving_swift_container": cont}
+ else:
+ nm = "%s/%s" % (cont, utils.get_name(img))
+ body["input"] = {
+ "image_properties": {"name": img_name or img},
+ "import_from": nm,
+ "import_from_format": img_format or DEFAULT_FORMAT}
+ return body
+
+
+ def create(self, name, *args, **kwargs):
+ """
+ Standard task creation, but first check for the existence of the
+ containers, and raise an exception if they don't exist.
+ """
+ cont = kwargs.get("cont")
+ if cont:
+ # Verify that it exists. If it doesn't, a NoSuchContainer exception
+ # will be raised.
+ pyrax.cloudfiles.get_container(cont)
+ return super(ImageTasksManager, self).create(name, *args, **kwargs)
+
+
+
+class JSONSchemaManager(BaseManager):
+ """
+ Manager class for retrieving JSON schemas.
+ """
+ def _create_body(self, name):
+ """
+ Not used.
+ """
+ pass
+
+
+ def images(self):
+ """
+ Returns a json-schema document that represents an image members entity,
+ which is a container of image member entities.
+ """
+ uri = "/%s/images" % self.uri_base
+ resp, resp_body = self.api.method_get(uri)
+ return resp_body
+
+
+ def image(self):
+ """
+ Returns a json-schema document that represents a single image entity.
+ """
+ uri = "/%s/image" % self.uri_base
+ resp, resp_body = self.api.method_get(uri)
+ return resp_body
+
+
+ def image_members(self):
+ """
+ Returns a json-schema document that represents an image members entity
+ (a container of member entities).
+ """
+ uri = "/%s/members" % self.uri_base
+ resp, resp_body = self.api.method_get(uri)
+ return resp_body
+
+
+ def image_member(self):
+ """
+ Returns a json-schema document that represents an image member entity.
+ (a container of member entities).
+ """
+ uri = "/%s/member" % self.uri_base
+ resp, resp_body = self.api.method_get(uri)
+ return resp_body
+
+
+ def image_tasks(self):
+ """
+ Returns a json-schema document that represents a container of tasks
+ entities.
+ """
+ uri = "/%s/tasks" % self.uri_base
+ resp, resp_body = self.api.method_get(uri)
+ return resp_body
+
+
+ def image_task(self):
+ """
+ Returns a json-schema document that represents an task entity.
+ """
+ uri = "/%s/task" % self.uri_base
+ resp, resp_body = self.api.method_get(uri)
+ return resp_body
+
+
+
+class ImageClient(BaseClient):
+ """
+ This is the primary class for interacting with Images.
+ """
+ name = "Images"
+
+
+ def _configure_manager(self):
+ """
+ Create the manager to handle queues.
+ """
+ self._manager = ImageManager(self, resource_class=Image,
+ response_key="", plural_response_key="images",
+ uri_base="images")
+ self._tasks_manager = ImageTasksManager(self, resource_class=ImageTask,
+ response_key="", plural_response_key="tasks",
+ uri_base="tasks")
+ self._schema_manager = JSONSchemaManager(self, resource_class=None,
+ response_key="", plural_response_key="", uri_base="schemas")
+
+
+ def list(self, limit=None, marker=None, name=None, visibility=None,
+ member_status=None, owner=None, tag=None, status=None,
+ size_min=None, size_max=None, sort_key=None, sort_dir=None):
+ """
+ Returns a list of resource objects. Pagination is supported through the
+ optional 'marker' and 'limit' parameters. Filtering the returned value
+ is possible by specifying values for any of the other parameters.
+ """
+ return self._manager.list(limit=limit, marker=marker, name=name,
+ visibility=visibility, member_status=member_status,
+ owner=owner, tag=tag, status=status, size_min=size_min,
+ size_max=size_max, sort_key=sort_key, sort_dir=sort_dir)
+
+
+ def list_all(self, name=None, visibility=None, member_status=None,
+ owner=None, tag=None, status=None, size_min=None, size_max=None,
+ sort_key=None, sort_dir=None):
+ """
+ Returns all of the images in one call, rather than in paginated batches.
+ The same filtering options available in list() apply here, with the
+ obvious exception of limit and marker.
+ """
+ return self._manager.list_all(name=name, visibility=visibility,
+ member_status=member_status, owner=owner, tag=tag,
+ status=status, size_min=size_min, size_max=size_max,
+ sort_key=sort_key, sort_dir=sort_dir)
+
+
+ def update(self, img, value_dict):
+ """
+ Accepts an image reference (object or ID) and dictionary of key/value
+ pairs, where the key is an attribute of the image, and the value is the
+ desired new value for that image.
+ """
+ return self._manager.update(img, value_dict)
+
+
+ def change_image_name(self, img, newname):
+ """
+ Image name can be changed via the update() method. This is simply a
+ convenience method.
+ """
+ return self.update(img, {"name": newname})
+
+
+ @assure_image
+ def list_image_members(self, img):
+ """
+ Returns a list of members (users) of the specified image.
+ """
+ return img.list_members()
+
+
+ @assure_image
+ def get_image_member(self, img, member):
+ """
+ Returns the ImageMember object representing the specified member for the
+ specified image.
+ """
+ return img.get_member(member)
+
+
+ @assure_image
+ def add_image_member(self, img, project_id):
+ """
+ Adds the project (tenant) represented by the project_id as a member of
+ the specified image.
+ """
+ return img.add_member(project_id)
+
+
+ @assure_image
+ def delete_image_member(self, img, project_id):
+ """
+ Removes the project (tenant) represented by the project_id as a member
+ of the specified image.
+ """
+ return img.delete_member(project_id)
+
+
+ def update_image_member(self, img_id, status):
+ """
+ Updates the image whose ID is given with the status specified. This
+ must be called by the user whose project_id is in the members for the
+ image; that is, the user with whom the image is being shared. If called
+ by the owner of the image, an `InvalidImageMember` exception will be
+ raised.
+
+ Valid values for 'status' include:
+ pending
+ accepted
+ rejected
+
+ Any other value will result in an `InvalidImageMemberStatus` exception
+ being raised.
+ """
+ return self._manager.update_image_member(img_id, status)
+
+
+ @assure_image
+ def add_image_tag(self, img, tag):
+ """
+ Adds the tag to the specified image.
+ """
+ return img.add_tag(tag)
+
+
+ @assure_image
+ def delete_image_tag(self, img, tag):
+ """
+ Deletes the tag from the specified image.
+ """
+ return img.delete_tag(tag)
+
+
+ def list_tasks(self):
+ """
+ Returns a list of all tasks.
+ """
+ return self._tasks_manager.list()
+
+
+ def get_task(self, task):
+ """
+ Returns the ImageTask object for the supplied ID.
+ """
+ return self._tasks_manager.get(task)
+
+
+ def export_task(self, img, cont):
+ """
+ Creates a task to export the specified image to the swift container
+ named in the 'cont' parameter. If the container does not exist, a
+ NoSuchContainer exception is raised.
+
+ The 'img' parameter can be either an Image object or the ID of an
+ image. If these do not correspond to a valid image, a NotFound
+ exception is raised.
+ """
+ return self._tasks_manager.create("export", img=img, cont=cont)
+
+
+ def import_task(self, img, cont, img_format=None, img_name=None):
+ """
+ Creates a task to import the specified image from the swift container
+ named in the 'cont' parameter. The new image will be named the same as
+ the object in the container unless you specify a value for the
+ 'img_name' parameter.
+
+ By default it is assumed that the image is in 'vhd' format; if it is
+ another format, you must specify that in the 'img_format' parameter.
+ """
+ return self._tasks_manager.create("import", img=img, cont=cont,
+ img_format=img_format, img_name=img_name)
+
+
+ def get_images_schema(self):
+ """
+ Returns a json-schema document that represents an image members entity,
+ which is a container of image member entities.
+ """
+ return self._schema_manager.images()
+
+
+ def get_image_schema(self):
+ """
+ Returns a json-schema document that represents a single image entity.
+ """
+ return self._schema_manager.image()
+
+
+ def get_image_members_schema(self):
+ """
+ Returns a json-schema document that represents an image members entity
+ (a container of member entities).
+ """
+ return self._schema_manager.image_members()
+
+
+ def get_image_member_schema(self):
+ """
+ Returns a json-schema document that represents an image member entity.
+ (a container of member entities).
+ """
+ return self._schema_manager.image_member()
+
+
+ def get_image_tasks_schema(self):
+ """
+ Returns a json-schema document that represents a container of tasks
+ entities.
+ """
+ return self._schema_manager.image_tasks()
+
+
+ def get_image_task_schema(self):
+ """
+ Returns a json-schema document that represents an task entity.
+ """
+ return self._schema_manager.image_task()
diff --git a/pyrax/manager.py b/pyrax/manager.py
index 48e18a1b..94453138 100644
--- a/pyrax/manager.py
+++ b/pyrax/manager.py
@@ -145,6 +145,17 @@ def _list(self, uri, obj_class=None, body=None, return_raw=False):
if obj_class is None:
obj_class = self.resource_class
+ data = self._data_from_response(resp_body)
+ return [obj_class(self, res, loaded=False)
+ for res in data if res]
+
+
+ def _data_from_response(self, resp_body):
+ """
+ This works for most API responses, but some don't structure their
+ listing responses the same way, so overriding this method allows
+ subclasses to handle extraction for those outliers.
+ """
data = resp_body.get(self.plural_response_key, resp_body)
# NOTE(ja): keystone returns values as list as {"values": [ ... ]}
# unlike other services which just return the list...
@@ -153,8 +164,7 @@ def _list(self, uri, obj_class=None, body=None, return_raw=False):
data = data["values"]
except KeyError:
pass
- return [obj_class(self, res, loaded=False)
- for res in data if res]
+ return data
def _head(self, uri):
diff --git a/pyrax/queueing.py b/pyrax/queueing.py
index 75fa281d..bf14f1e4 100644
--- a/pyrax/queueing.py
+++ b/pyrax/queueing.py
@@ -315,9 +315,10 @@ def _iterate_list(self, include_claimed, echo, marker, limit):
"""
ret = []
if limit is None:
- limit = MSG_LIMIT
- this_limit = min(MSG_LIMIT, limit)
- limit = max(0, (limit - this_limit))
+ this_limit = MSG_LIMIT
+ else:
+ this_limit = min(MSG_LIMIT, limit)
+ limit = limit - this_limit
uri = "/%s?include_claimed=%s&echo=%s" % (self.uri_base,
json.dumps(include_claimed), json.dumps(echo))
qs_parts = []
@@ -335,7 +336,7 @@ def _iterate_list(self, include_claimed, echo, marker, limit):
marker = _parse_marker(resp_body)
loop = 0
- if limit and marker:
+ if ((limit is None) or limit > 0) and marker:
loop += 1
ret.extend(self._iterate_list(include_claimed, echo, marker, limit))
return ret
diff --git a/pyrax/resource.py b/pyrax/resource.py
index 52c292fb..960d8111 100644
--- a/pyrax/resource.py
+++ b/pyrax/resource.py
@@ -21,6 +21,8 @@
Base utilities to build API operation managers and objects on top of.
"""
+import six
+
import pyrax
import pyrax.utils as utils
@@ -66,7 +68,7 @@ def _add_details(self, info):
corresponding attributes on the object.
"""
for (key, val) in info.iteritems():
- if isinstance(key, unicode):
+ if isinstance(key, six.text_type):
key = key.encode(pyrax.get_encoding())
setattr(self, key, val)
diff --git a/pyrax/utils.py b/pyrax/utils.py
index b411400d..409d782b 100644
--- a/pyrax/utils.py
+++ b/pyrax/utils.py
@@ -1,6 +1,8 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
+from __future__ import print_function
+
import datetime
import email.utils
import fnmatch
@@ -24,6 +26,8 @@
import pdb as pudb
trace = pudb.set_trace
+import six
+
import pyrax
import pyrax.exceptions as exc
@@ -171,7 +175,7 @@ def random_unicode(length=20):
"""
def get_char():
return unichr(random.randint(32, 1000))
- chars = u"".join([get_char() for ii in xrange(length)])
+ chars = u"".join([get_char() for ii in six.moves.range(length)])
return _join_chars(chars, length)
@@ -348,7 +352,7 @@ def _wait_until(obj, att, desired, callback, interval, attempts, verbose,
for vatt in verbose_atts:
vattval = getattr(obj, vatt, None)
msgs.append("%s=%s" % (vatt, vattval))
- print " ".join(msgs)
+ print(" ".join(msgs))
if attval in desired:
return obj
time.sleep(interval)
@@ -399,7 +403,7 @@ def iso_time_string(val, show_tzinfo=False):
"""
if not val:
return ""
- if isinstance(val, basestring):
+ if isinstance(val, six.string_types):
dt = _parse_datetime_string(val)
else:
dt = val
@@ -424,7 +428,7 @@ def rfc2822_format(val):
represents the value in RFC 2822 format. If a string is passed it is
returned unchanged.
"""
- if isinstance(val, basestring):
+ if isinstance(val, six.string_types):
return val
elif isinstance(val, (datetime.datetime, datetime.date)):
# Convert to a timestamp
@@ -445,7 +449,7 @@ def to_timestamp(val):
# If we're given a number, give it right back - it's already a timestamp.
if isinstance(val, numbers.Number):
return val
- elif isinstance(val, basestring):
+ elif isinstance(val, six.string_types):
dt = _parse_datetime_string(val)
else:
dt = val
@@ -457,7 +461,7 @@ def get_id(id_or_obj):
Returns the 'id' attribute of 'id_or_obj' if present; if not,
returns 'id_or_obj'.
"""
- if isinstance(id_or_obj, (basestring, int)):
+ if isinstance(id_or_obj, six.string_types + (int,)):
# It's an ID
return id_or_obj
try:
@@ -471,7 +475,7 @@ def get_name(name_or_obj):
Returns the 'name' attribute of 'name_or_obj' if present; if not,
returns 'name_or_obj'.
"""
- if isinstance(name_or_obj, basestring):
+ if isinstance(name_or_obj, six.string_types):
# It's a name
return name_or_obj
try:
@@ -494,6 +498,15 @@ def params_to_dict(params, dct, local_dict):
return dct
+def dict_to_qs(dct):
+ """
+ Takes a dictionary and uses it to create a query string.
+ """
+ itms = ["%s=%s" % (key, val) for key, val in list(dct.items())
+ if val is not None]
+ return "&".join(itms)
+
+
def match_pattern(nm, patterns):
"""
Compares `nm` with the supplied patterns, and returns True if it matches
@@ -607,8 +620,8 @@ def slugify(value):
import unicodedata
_slugify_strip_re = re.compile(r"[^\w\s-]")
_slugify_hyphenate_re = re.compile(r"[-\s]+")
- if not isinstance(value, unicode):
- value = unicode(value)
+ if not isinstance(value, six.text_type):
+ value = six.text_type(value)
value = unicodedata.normalize("NFKD", value).encode("ascii", "ignore")
- value = unicode(_slugify_strip_re.sub("", value).strip().lower())
+ value = six.text_type(_slugify_strip_re.sub("", value).strip().lower())
return _slugify_hyphenate_re.sub("-", value)
diff --git a/pyrax/version.py b/pyrax/version.py
index aa89f72a..93c262fa 100644
--- a/pyrax/version.py
+++ b/pyrax/version.py
@@ -1,4 +1,4 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
-version = "1.6.4"
+version = "1.7.0"
diff --git a/samples/auth_creds_file.py b/samples/auth_creds_file.py
index b4440c73..c87ccf93 100644
--- a/samples/auth_creds_file.py
+++ b/samples/auth_creds_file.py
@@ -16,6 +16,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+from __future__ import print_function
+
import os
import pyrax
@@ -27,14 +29,15 @@
# [rackspace_cloud]
# username = myusername
# api_key = 01234567890abcdef
-print
-print "Using credentials file"
+print()
+print("Using credentials file")
# Note: you can name this file whatever you like.
creds_file = os.path.expanduser("~/.rackspace_cloud_credentials")
try:
pyrax.set_credential_file(creds_file)
except exc.AuthenticationFailed:
- print "Did you remember to replace the credential file with your actual",
- print "username and api_key?"
-print "authenticated =", pyrax.identity.authenticated
-print
+ print("Did you remember to replace the credential file with your actual",
+ end=' ')
+ print("username and api_key?")
+print("authenticated =", pyrax.identity.authenticated)
+print()
diff --git a/samples/auth_direct.py b/samples/auth_direct.py
index 9c51f6f1..17f0ecbf 100644
--- a/samples/auth_direct.py
+++ b/samples/auth_direct.py
@@ -16,6 +16,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+from __future__ import print_function
+
import os
import pyrax
@@ -24,11 +26,11 @@
pyrax.set_setting("identity_type", "rackspace")
# Pass credentials directly (replace with your credentials)
-print "Pass directly:"
+print("Pass directly:")
try:
pyrax.set_credentials("real_username", "real_api_key")
except exc.AuthenticationFailed:
- print "Did you remember to replace the credentials with your actual",
- print "username and api_key?"
-print "authenticated =", pyrax.identity.authenticated
-print
+ print("Did you remember to replace the credentials with your actual", end=' ')
+ print("username and api_key?")
+print("authenticated =", pyrax.identity.authenticated)
+print()
diff --git a/samples/autoscale/add_policy.py b/samples/autoscale/add_policy.py
index f64c23e9..b7e6d15c 100644
--- a/samples/autoscale/add_policy.py
+++ b/samples/autoscale/add_policy.py
@@ -16,6 +16,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+from __future__ import print_function
+
import os
import pyrax
@@ -32,32 +34,32 @@ def safe_int(val, allow_zero=True):
try:
ret = int(val)
except ValueError:
- print "Sorry, '%s' is not a valid integer." % val
+ print("Sorry, '%s' is not a valid integer." % val)
return False
if not allow_zero and ret == 0:
- print "Please enter a non-zero integer."
+ print("Please enter a non-zero integer.")
return False
return ret
# Get the current scaling groups
sgs = au.list()
if not sgs:
- print "There are no scaling groups defined. Please run the "\
- "'create_scaling_group.py' script first."
+ print("There are no scaling groups defined. Please run the "
+ "'create_scaling_group.py' script first.")
exit()
-print
-print "Available Scaling Groups:"
+print()
+print("Available Scaling Groups:")
for pos, sg in enumerate(sgs):
- print "%s - %s" % (pos, sg.name)
+ print("%s - %s" % (pos, sg.name))
answer = raw_input("Enter the number of the scaling group you wish to add a "
"policy to: ")
if not answer:
- print "Nothing entered; exiting."
+ print("Nothing entered; exiting.")
exit()
intanswer = safe_int(answer)
if not 0 <= intanswer < len(sgs):
- print "The number '%s' does not correspond to any scaling group." % answer
+ print("The number '%s' does not correspond to any scaling group." % answer)
exit()
sg = sgs[intanswer]
@@ -78,4 +80,4 @@ def safe_int(val, allow_zero=True):
policy = au.add_policy(sg, pname, "webhook", cooldown, change, is_percent)
-print "Policy added: %s" % policy
+print("Policy added: %s" % policy)
diff --git a/samples/autoscale/add_webhook.py b/samples/autoscale/add_webhook.py
index f5943249..de2352f2 100644
--- a/samples/autoscale/add_webhook.py
+++ b/samples/autoscale/add_webhook.py
@@ -16,6 +16,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+from __future__ import print_function
+
import os
import pyrax
@@ -32,51 +34,51 @@ def safe_int(val, allow_zero=True):
try:
ret = int(val)
except ValueError:
- print "Sorry, '%s' is not a valid integer." % val
+ print("Sorry, '%s' is not a valid integer." % val)
return False
if not allow_zero and ret == 0:
- print "Please enter a non-zero integer."
+ print("Please enter a non-zero integer.")
return False
return ret
# Get the current scaling groups
sgs = au.list()
if not sgs:
- print "There are no scaling groups defined."
+ print("There are no scaling groups defined.")
exit()
-print
-print "Available Scaling Groups:"
+print()
+print("Available Scaling Groups:")
for pos, sg in enumerate(sgs):
- print "%s - %s" % (pos, sg.name)
+ print("%s - %s" % (pos, sg.name))
intanswer = -1
while intanswer < 0:
answer = raw_input("Enter the number of the scaling group: ")
if not answer:
- print "Nothing entered; exiting."
+ print("Nothing entered; exiting.")
exit()
intanswer = safe_int(answer)
if intanswer is False:
intanswer = -1
continue
if not 0 <= intanswer < len(sgs):
- print "The number '%s' does not correspond to any scaling group." % answer
+ print("The number '%s' does not correspond to any scaling group." % answer)
intanswer = -1
policies = sg.list_policies()
if not policies:
- print "There are no policies defined for this scaling group. You can only "\
- "add webhooks to existing policies."
+ print("There are no policies defined for this scaling group. You can only "
+ "add webhooks to existing policies.")
exit()
for pos, policy in enumerate(policies):
- print "%s - %s" % (pos, policy.name)
+ print("%s - %s" % (pos, policy.name))
answer = raw_input("Enter the number of the policy: ")
if not answer:
- print "Nothing entered; exiting."
+ print("Nothing entered; exiting.")
exit()
intanswer = safe_int(answer)
if not 0 <= intanswer < len(policies):
- print "The number '%s' does not correspond to any policy." % answer
+ print("The number '%s' does not correspond to any policy." % answer)
exit()
policy = policies[intanswer]
@@ -95,6 +97,6 @@ def safe_int(val, allow_zero=True):
hook = policy.add_webhook(name, metadata=metadata)
-print
-print
-print "Webhook added: %s" % hook
+print()
+print()
+print("Webhook added: %s" % hook)
diff --git a/samples/autoscale/create_scaling_group.py b/samples/autoscale/create_scaling_group.py
index 5d5a68d3..8b6d872b 100644
--- a/samples/autoscale/create_scaling_group.py
+++ b/samples/autoscale/create_scaling_group.py
@@ -16,6 +16,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+from __future__ import print_function
+
import os
import pyrax
@@ -35,10 +37,10 @@ def safe_int(val, allow_zero=True):
try:
ret = int(val)
except ValueError:
- print "Sorry, '%s' is not a valid integer." % val
+ print("Sorry, '%s' is not a valid integer." % val)
return False
if not allow_zero and ret == 0:
- print "Please enter a non-zero integer."
+ print("Please enter a non-zero integer.")
return False
return ret
@@ -49,17 +51,17 @@ def get_yn(prompt):
answer = raw_input("%s (y/n) " % prompt)
yn = answer[0].lower()
if yn not in "yn":
- print "Please answer 'y' or 'n', not '%s'." % answer
+ print("Please answer 'y' or 'n', not '%s'." % answer)
answer = None
continue
return (yn == "y")
def select_lbs():
- print "Getting a list of your load balancers..."
+ print("Getting a list of your load balancers...")
lbs = clb.list()
for pos, lb in enumerate(lbs):
- print "%s - %s (port %s)" % (pos, lb.name, lb.port)
+ print("%s - %s (port %s)" % (pos, lb.name, lb.port))
chosen = raw_input("Enter the number(s) of the load balancer to use, "
"separated by commas: ")
lb_ints = [safe_int(num) for num in chosen.split(",")]
@@ -91,7 +93,7 @@ def select_lbs():
max_entities = safe_int(raw_input("Enter the maximum entities: (%s-1000)"
% min_entities), False)
if max_entities and (max_entities < min_entities):
- print "The value for max_entities must be greater than min_entities."
+ print("The value for max_entities must be greater than min_entities.")
# Configure the server launch settings.
server_name = ""
@@ -99,10 +101,10 @@ def select_lbs():
server_name = raw_input("Enter the name base for the servers in this "
"scaling group: ")
-print "Getting a list of images..."
+print("Getting a list of images...")
imgs = cs.list_images()
for pos, img in enumerate(imgs):
- print "%s - %s" % (pos, img.name)
+ print("%s - %s" % (pos, img.name))
answer = -1
while answer < 0:
answer = safe_int(raw_input("Enter the number of the image to use: "))
@@ -111,10 +113,10 @@ def select_lbs():
answer = -1
continue
if not 0 <= answer < len(imgs):
- print "The number '%s' does not correspond to any image." % answer
+ print("The number '%s' does not correspond to any image." % answer)
answer = -1
image = imgs[answer]
-print "You selected: %s." % image.name
+print("You selected: %s." % image.name)
# Use a small flavor
flavor = "performance1-1"
@@ -129,7 +131,7 @@ def select_lbs():
while add_lb:
lbs = select_lbs()
if not lbs:
- print "No valid load balancers were entered."
+ print("No valid load balancers were entered.")
add_lb = get_yn("Do you want to try again?")
continue
add_lb = False
@@ -139,8 +141,8 @@ def select_lbs():
server_name, image, flavor, load_balancers=load_balancers,
disk_config=disk_config, metadata=metadata)
-print
-print
-print "Scaling Group:", sg.name
-print "ID:", sg.id
-print "State:", sg.get_state()
+print()
+print()
+print("Scaling Group:", sg.name)
+print("ID:", sg.id)
+print("State:", sg.get_state())
diff --git a/samples/autoscale/delete_policy.py b/samples/autoscale/delete_policy.py
index fe2cb7b4..36c95291 100644
--- a/samples/autoscale/delete_policy.py
+++ b/samples/autoscale/delete_policy.py
@@ -16,6 +16,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+from __future__ import print_function
+
import os
import pyrax
@@ -32,51 +34,51 @@ def safe_int(val, allow_zero=True):
try:
ret = int(val)
except ValueError:
- print "Sorry, '%s' is not a valid integer." % val
+ print("Sorry, '%s' is not a valid integer." % val)
return False
if not allow_zero and ret == 0:
- print "Please enter a non-zero integer."
+ print("Please enter a non-zero integer.")
return False
return ret
# Get the current scaling groups
sgs = au.list()
if not sgs:
- print "There are no scaling groups defined."
+ print("There are no scaling groups defined.")
exit()
-print
-print "Available Scaling Groups:"
+print()
+print("Available Scaling Groups:")
for pos, sg in enumerate(sgs):
- print "%s - %s" % (pos, sg.name)
+ print("%s - %s" % (pos, sg.name))
intanswer = -1
while intanswer < 0:
answer = raw_input("Enter the number of the scaling group: ")
if not answer:
- print "Nothing entered; exiting."
+ print("Nothing entered; exiting.")
exit()
intanswer = safe_int(answer)
if intanswer is False:
intanswer = -1
continue
if not 0 <= intanswer < len(sgs):
- print "The number '%s' does not correspond to any scaling group." % answer
+ print("The number '%s' does not correspond to any scaling group." % answer)
intanswer = -1
policies = sg.list_policies()
if not policies:
- print "There are no policies defined for this scaling group."
+ print("There are no policies defined for this scaling group.")
exit()
for pos, policy in enumerate(policies):
- print "%s - %s" % (pos, policy.name)
+ print("%s - %s" % (pos, policy.name))
answer = raw_input("Enter the number of the policy to delete: ")
if not answer:
- print "Nothing entered; exiting."
+ print("Nothing entered; exiting.")
exit()
intanswer = safe_int(answer)
if not 0 <= intanswer < len(policies):
- print "The number '%s' does not correspond to any policy." % answer
+ print("The number '%s' does not correspond to any policy." % answer)
exit()
policy = policies[intanswer]
policy.delete()
-print "Policy '%s' has been deleted." % policy.name
+print("Policy '%s' has been deleted." % policy.name)
diff --git a/samples/autoscale/delete_scaling_group.py b/samples/autoscale/delete_scaling_group.py
index 4d89e7d7..fdd06ede 100644
--- a/samples/autoscale/delete_scaling_group.py
+++ b/samples/autoscale/delete_scaling_group.py
@@ -16,6 +16,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+from __future__ import print_function
+
import os
import pyrax
@@ -28,27 +30,27 @@
# Get the current scaling groups
sgs = au.list()
if not sgs:
- print "There are no scaling groups defined."
+ print("There are no scaling groups defined.")
exit()
-print
-print "Available Scaling Groups:"
+print()
+print("Available Scaling Groups:")
for pos, sg in enumerate(sgs):
- print "%s - %s" % (pos, sg.name)
+ print("%s - %s" % (pos, sg.name))
answer = raw_input("Enter the number of the scaling group to delete: ")
if not answer:
- print "Nothing entered; exiting."
+ print("Nothing entered; exiting.")
exit()
try:
intanswer = int(answer)
except ValueError:
- print "'%s' is not a valid number; exiting." % answer
+ print("'%s' is not a valid number; exiting." % answer)
exit()
if not 0 <= intanswer < len(sgs):
- print "The number '%s' does not correspond to any scaling group." % answer
+ print("The number '%s' does not correspond to any scaling group." % answer)
exit()
sg_del = sgs[intanswer]
sg_del.update(min_entities=0, max_entities=0)
sg_del.delete()
-print "Scaling group '%s' has been deleted." % sg_del.name
+print("Scaling group '%s' has been deleted." % sg_del.name)
diff --git a/samples/autoscale/delete_webhook.py b/samples/autoscale/delete_webhook.py
index 6d897fa3..0f11a43a 100644
--- a/samples/autoscale/delete_webhook.py
+++ b/samples/autoscale/delete_webhook.py
@@ -16,6 +16,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+from __future__ import print_function
+
import os
import pyrax
@@ -32,69 +34,69 @@ def safe_int(val, allow_zero=True):
try:
ret = int(val)
except ValueError:
- print "Sorry, '%s' is not a valid integer." % val
+ print("Sorry, '%s' is not a valid integer." % val)
return False
if not allow_zero and ret == 0:
- print "Please enter a non-zero integer."
+ print("Please enter a non-zero integer.")
return False
return ret
# Get the current scaling groups
sgs = au.list()
if not sgs:
- print "There are no scaling groups defined."
+ print("There are no scaling groups defined.")
exit()
-print
-print "Available Scaling Groups:"
+print()
+print("Available Scaling Groups:")
for pos, sg in enumerate(sgs):
- print "%s - %s" % (pos, sg.name)
+ print("%s - %s" % (pos, sg.name))
intanswer = -1
while intanswer < 0:
answer = raw_input("Enter the number of the scaling group: ")
if not answer:
- print "Nothing entered; exiting."
+ print("Nothing entered; exiting.")
exit()
intanswer = safe_int(answer)
if intanswer is False:
intanswer = -1
continue
if not 0 <= intanswer < len(sgs):
- print "The number '%s' does not correspond to any scaling group." % answer
+ print("The number '%s' does not correspond to any scaling group." % answer)
intanswer = -1
policies = sg.list_policies()
if not policies:
- print "There are no policies defined for this scaling group. You can only "\
- "add webhooks to existing policies."
+ print("There are no policies defined for this scaling group. You can only "
+ "add webhooks to existing policies.")
exit()
for pos, policy in enumerate(policies):
- print "%s - %s" % (pos, policy.name)
+ print("%s - %s" % (pos, policy.name))
answer = raw_input("Enter the number of the policy: ")
if not answer:
- print "Nothing entered; exiting."
+ print("Nothing entered; exiting.")
exit()
intanswer = safe_int(answer)
if not 0 <= intanswer < len(policies):
- print "The number '%s' does not correspond to any policy." % answer
+ print("The number '%s' does not correspond to any policy." % answer)
exit()
policy = policies[intanswer]
webhooks = policy.list_webhooks()
if not webhooks:
- print "There are no webhooks defined for this policy."
+ print("There are no webhooks defined for this policy.")
exit()
for pos, webhook in enumerate(webhooks):
- print "%s - %s" % (pos, webhook.name)
+ print("%s - %s" % (pos, webhook.name))
answer = raw_input("Enter the number of the webhook: ")
if not answer:
- print "Nothing entered; exiting."
+ print("Nothing entered; exiting.")
exit()
intanswer = safe_int(answer)
if not 0 <= intanswer < len(webhooks):
- print "The number '%s' does not correspond to any webhook." % answer
+ print("The number '%s' does not correspond to any webhook." % answer)
exit()
webhook = webhooks[intanswer]
webhook.delete()
-print
-print "Webhook '%s' has been deleted." % webhook.name
+print()
+print("Webhook '%s' has been deleted." % webhook.name)
diff --git a/samples/cloud_blockstorage/attach_detach_volume.py b/samples/cloud_blockstorage/attach_detach_volume.py
index 3e3b6c1d..b093859e 100644
--- a/samples/cloud_blockstorage/attach_detach_volume.py
+++ b/samples/cloud_blockstorage/attach_detach_volume.py
@@ -16,6 +16,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+from __future__ import print_function
+
import os
import sys
@@ -30,18 +32,18 @@
try:
server = cs.servers.find(name="sample_server")
except cs.exceptions.NotFound as e:
- print
- print "Before running this sample, create a server named 'sample_server' "
- print "and wait for it to be in an ACTIVE state."
+ print()
+ print("Before running this sample, create a server named 'sample_server' ")
+ print("and wait for it to be in an ACTIVE state.")
answer = raw_input("Do you wish to have this server created for you? [y/N]")
if answer.lower().startswith("y"):
ubu_image = [img for img in cs.images.list()
if "Ubuntu" in img.name][0]
flavor_1GB = [flavor for flavor in cs.flavors.list()
if flavor.ram == 1024][0]
- print "Creating the server..."
+ print("Creating the server...")
server = cs.servers.create("sample_server", ubu_image.id, flavor_1GB.id)
- print "Server created; waiting for it to become active..."
+ print("Server created; waiting for it to become active...")
pyrax.utils.wait_until(server, "status", "ACTIVE", attempts=0,
verbose=True)
else:
@@ -49,22 +51,22 @@
# Create a 100GB SATA volume, and attach it to the server
vol = cbs.create(name="sample_volume", size=100, volume_type="SATA")
-print "New volume:", vol.name
-print "Attaching to:", server
-print "It may take several seconds for the attachment to complete."
+print("New volume:", vol.name)
+print("Attaching to:", server)
+print("It may take several seconds for the attachment to complete.")
vol.attach_to_instance(server, mountpoint="/dev/xvdd")
pyrax.utils.wait_until(vol, "status", "in-use", interval=3, attempts=0,
verbose=True)
-print "Volume attachments:", vol.attachments
+print("Volume attachments:", vol.attachments)
# Now detach the volume
-print
-print "Detaching the volume..."
+print()
+print("Detaching the volume...")
vol.detach()
pyrax.utils.wait_until(vol, "status", "available", interval=3, attempts=0,
verbose=True)
-print "Attachments:", vol.attachments
+print("Attachments:", vol.attachments)
# Delete the volume
vol.delete()
-print "Deleted"
+print("Deleted")
diff --git a/samples/cloud_blockstorage/create_snapshot.py b/samples/cloud_blockstorage/create_snapshot.py
index 56dee492..eb40b554 100644
--- a/samples/cloud_blockstorage/create_snapshot.py
+++ b/samples/cloud_blockstorage/create_snapshot.py
@@ -16,6 +16,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+from __future__ import print_function
+
import os
import sys
@@ -31,25 +33,25 @@
snap = vol.create_snapshot("sample_snap")
-print "Volume:", vol
-print "Snapshot:", snap
-print
-print "You have to wait until the snapshot finishes being created before"
-print "it can be deleted. Press Ctrl-C to interrupt."
+print("Volume:", vol)
+print("Snapshot:", snap)
+print()
+print("You have to wait until the snapshot finishes being created before")
+print("it can be deleted. Press Ctrl-C to interrupt.")
try:
pyrax.utils.wait_until(snap, "status", "available", attempts=0, verbose=True)
except KeyboardInterrupt:
- print
- print "Process interrupted."
- print "Be sure to manually delete this snapshot when it completes."
+ print()
+ print("Process interrupted.")
+ print("Be sure to manually delete this snapshot when it completes.")
sys.exit(0)
-print
-print "Deleting snapshot..."
+print()
+print("Deleting snapshot...")
snap.delete()
try:
vol.delete()
except exc.VolumeNotAvailable:
- print "Could not delete volume; snapshot deletion has not completed yet."
- print "Please be sure to delete the volume manually."
- print
-print "Done."
+ print("Could not delete volume; snapshot deletion has not completed yet.")
+ print("Please be sure to delete the volume manually.")
+ print()
+print("Done.")
diff --git a/samples/cloud_blockstorage/create_volume.py b/samples/cloud_blockstorage/create_volume.py
index 1137b5df..b9f52bf2 100644
--- a/samples/cloud_blockstorage/create_volume.py
+++ b/samples/cloud_blockstorage/create_volume.py
@@ -16,6 +16,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+from __future__ import print_function
+
import os
import pyrax
@@ -28,9 +30,9 @@
sata_vol = cbs.create(name="my_standard_volume", size=500, volume_type="SATA")
ssd_vol = cbs.create(name="my_fast_volume", size=500, volume_type="SSD")
-print "SATA:", sata_vol
-print
-print "SSD:", ssd_vol
-print
-print "To delete these volumes, run 'delete_volume.py'"
-print
+print("SATA:", sata_vol)
+print()
+print("SSD:", ssd_vol)
+print()
+print("To delete these volumes, run 'delete_volume.py'")
+print()
diff --git a/samples/cloud_blockstorage/delete_volume.py b/samples/cloud_blockstorage/delete_volume.py
index 9ce1173d..018c02b0 100644
--- a/samples/cloud_blockstorage/delete_volume.py
+++ b/samples/cloud_blockstorage/delete_volume.py
@@ -16,6 +16,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+from __future__ import print_function
+
import os
import pyrax
@@ -30,11 +32,11 @@
try:
vol = cbs.findall(name=nm)[0]
except IndexError:
- print "There is no volume named '%s'. Skipping..." % nm
+ print("There is no volume named '%s'. Skipping..." % nm)
vol = None
if vol:
- print "Deleting", vol
+ print("Deleting", vol)
vol.delete()
-print
-print "Done."
-print
+print()
+print("Done.")
+print()
diff --git a/samples/cloud_databases/add_database.py b/samples/cloud_databases/add_database.py
index 5a700ffa..857d32bc 100644
--- a/samples/cloud_databases/add_database.py
+++ b/samples/cloud_databases/add_database.py
@@ -16,6 +16,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+from __future__ import print_function
+
import os
import sys
@@ -28,38 +30,38 @@
instances = cdb.list()
if not instances:
- print "There are no cloud database instances."
- print "Please create one and re-run this script."
+ print("There are no cloud database instances.")
+ print("Please create one and re-run this script.")
sys.exit()
-print
-print "Available Instances:"
+print()
+print("Available Instances:")
for pos, inst in enumerate(instances):
- print "%s: %s (%s, RAM=%s, volume=%s) Status=%s" % (pos, inst.name,
- inst.flavor.name, inst.flavor.ram, inst.volume.size, inst.status)
+ print("%s: %s (%s, RAM=%s, volume=%s) Status=%s" % (pos, inst.name,
+ inst.flavor.name, inst.flavor.ram, inst.volume.size, inst.status))
try:
sel = int(raw_input("Enter the number of the instance to which you want to "
"add a database: "))
except ValueError:
- print
- print "Invalid (non-numeric) entry."
- print
+ print()
+ print("Invalid (non-numeric) entry.")
+ print()
sys.exit()
try:
inst = instances[sel]
except IndexError:
- print
- print "Invalid selection."
- print
+ print()
+ print("Invalid selection.")
+ print()
sys.exit()
nm = raw_input("Enter the name of the new database to create in this instance: ")
db = inst.create_database(nm)
dbs = inst.list_databases()
-print
-print "Database %s has been created." % nm
-print "Current databases for instance '%s':" % inst.name
+print()
+print("Database %s has been created." % nm)
+print("Current databases for instance '%s':" % inst.name)
for db in dbs:
- print db.name
-print
+ print(db.name)
+print()
diff --git a/samples/cloud_databases/add_user.py b/samples/cloud_databases/add_user.py
index a5b57377..7e7d55a2 100644
--- a/samples/cloud_databases/add_user.py
+++ b/samples/cloud_databases/add_user.py
@@ -16,6 +16,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+from __future__ import print_function
+
import getpass
import os
import sys
@@ -29,41 +31,41 @@
instances = cdb.list()
if not instances:
- print "There are no cloud database instances."
- print "Please create one and re-run this script."
+ print("There are no cloud database instances.")
+ print("Please create one and re-run this script.")
sys.exit()
-print
-print "Available Instances:"
+print()
+print("Available Instances:")
for pos, inst in enumerate(instances):
- print "%s: %s (%s, RAM=%s, volume=%s) Status=%s" % (pos, inst.name,
- inst.flavor.name, inst.flavor.ram, inst.volume.size, inst.status)
+ print("%s: %s (%s, RAM=%s, volume=%s) Status=%s" % (pos, inst.name,
+ inst.flavor.name, inst.flavor.ram, inst.volume.size, inst.status))
try:
sel = int(raw_input("Enter the number of the instance to which you want to "
"add a user: "))
except ValueError:
- print
- print "Invalid (non-numeric) entry."
- print
+ print()
+ print("Invalid (non-numeric) entry.")
+ print()
sys.exit()
try:
inst = instances[sel]
except IndexError:
- print
- print "Invalid selection."
- print
+ print()
+ print("Invalid selection.")
+ print()
sys.exit()
-print
+print()
nm = raw_input("Enter the user name: ")
pw = getpass.getpass("Enter the password for this user: ")
-print
-print "Available Databases:"
+print()
+print("Available Databases:")
dbs = inst.list_databases()
for pos, db in enumerate(dbs):
- print "%s: %s" % (pos, db.name)
-print "Enter the numbers of the databases which the user can access,",
-print "separated by spaces: ",
+ print("%s: %s" % (pos, db.name))
+print("Enter the numbers of the databases which the user can access,", end=' ')
+print("separated by spaces: ", end=' ')
selected = raw_input()
selnums = [int(val) for val in selected.split()]
sel_dbs = [db.name for pos, db in enumerate(dbs)
@@ -71,6 +73,6 @@
user = inst.create_user(nm, pw, database_names=sel_dbs)
-print
-print "User '%s' has been created on instance '%s'." % (nm, inst.name)
-print
+print()
+print("User '%s' has been created on instance '%s'." % (nm, inst.name))
+print()
diff --git a/samples/cloud_databases/create_instance.py b/samples/cloud_databases/create_instance.py
index 93cadb6f..c6451972 100644
--- a/samples/cloud_databases/create_instance.py
+++ b/samples/cloud_databases/create_instance.py
@@ -16,6 +16,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+from __future__ import print_function
+
import os
import sys
@@ -29,23 +31,23 @@
flavors = cdb.list_flavors()
nm = raw_input("Enter a name for your new instance: ")
-print
-print "Available Flavors:"
+print()
+print("Available Flavors:")
for pos, flavor in enumerate(flavors):
- print "%s: %s, %s" % (pos, flavor.name, flavor.ram)
+ print("%s: %s, %s" % (pos, flavor.name, flavor.ram))
flav = int(raw_input("Select a Flavor for your new instance: "))
try:
selected = flavors[flav]
except IndexError:
- print "Invalid selection; exiting."
+ print("Invalid selection; exiting.")
sys.exit()
-print
+print()
sz = int(raw_input("Enter the volume size in GB (1-50): "))
instance = cdb.create(nm, flavor=selected, volume=sz)
-print "Name:", instance.name
-print "ID:", instance.id
-print "Status:", instance.status
-print "Flavor:", instance.flavor.name
+print("Name:", instance.name)
+print("ID:", instance.id)
+print("Status:", instance.status)
+print("Flavor:", instance.flavor.name)
diff --git a/samples/cloud_databases/delete_instance.py b/samples/cloud_databases/delete_instance.py
index b2501d32..4e121a0a 100644
--- a/samples/cloud_databases/delete_instance.py
+++ b/samples/cloud_databases/delete_instance.py
@@ -16,6 +16,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+from __future__ import print_function
+
import os
import sys
@@ -28,30 +30,30 @@
instances = cdb.list()
if not instances:
- print "There are no cloud database instances to delete."
+ print("There are no cloud database instances to delete.")
sys.exit()
-print
-print "Available Instances:"
+print()
+print("Available Instances:")
for pos, inst in enumerate(instances):
- print "%s: %s (%s, RAM=%s, volume=%s) Status=%s" % (pos, inst.name,
- inst.flavor.name, inst.flavor.ram, inst.volume.size, inst.status)
+ print("%s: %s (%s, RAM=%s, volume=%s) Status=%s" % (pos, inst.name,
+ inst.flavor.name, inst.flavor.ram, inst.volume.size, inst.status))
try:
sel = int(raw_input("Enter the number of the instance to delete: "))
except ValueError:
- print
- print "Invalid (non-numeric) entry."
- print
+ print()
+ print("Invalid (non-numeric) entry.")
+ print()
sys.exit()
try:
del_inst = instances[sel]
except IndexError:
- print
- print "Invalid selection."
- print
+ print()
+ print("Invalid selection.")
+ print()
sys.exit()
del_inst.delete()
-print
-print "Instance %s has been deleted." % del_inst.name
-print
+print()
+print("Instance %s has been deleted." % del_inst.name)
+print()
diff --git a/samples/cloud_databases/list_flavors.py b/samples/cloud_databases/list_flavors.py
index 32e701b1..9ecdace4 100644
--- a/samples/cloud_databases/list_flavors.py
+++ b/samples/cloud_databases/list_flavors.py
@@ -16,6 +16,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+from __future__ import print_function
+
import os
import sys
@@ -27,8 +29,8 @@
cdb = pyrax.cloud_databases
flavors = cdb.list_flavors()
-print
-print "Available Flavors:"
+print()
+print("Available Flavors:")
for flavor in flavors:
- print "Name: %s; RAM: %s, ID: %s" % (flavor.name, flavor.ram, flavor.id)
-print
+ print("Name: %s; RAM: %s, ID: %s" % (flavor.name, flavor.ram, flavor.id))
+print()
diff --git a/samples/cloud_dns/add_ptr_records.py b/samples/cloud_dns/add_ptr_records.py
index 647cd9e3..a77982f7 100644
--- a/samples/cloud_dns/add_ptr_records.py
+++ b/samples/cloud_dns/add_ptr_records.py
@@ -16,6 +16,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+from __future__ import print_function
+
import os
import sys
@@ -45,5 +47,5 @@
"ttl": 7200}
recs = dns.add_ptr_records(server, [ipv4_rec, ipv6_rec])
-print recs
-print
+print(recs)
+print()
diff --git a/samples/cloud_dns/add_records.py b/samples/cloud_dns/add_records.py
index 4ba7855e..f01fa5fe 100644
--- a/samples/cloud_dns/add_records.py
+++ b/samples/cloud_dns/add_records.py
@@ -16,6 +16,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+from __future__ import print_function
+
import os
import sys
@@ -41,9 +43,9 @@
dom = dns.create(name=domain_name, emailAddress="sample@example.edu",
ttl=900, comment="sample domain")
except exc.DomainCreationFailed as e:
- print "Domain creation failed:", e
- print "Domain created:", dom
- print
+ print("Domain creation failed:", e)
+ print("Domain created:", dom)
+ print()
# Substitute your actual domain name and IP addresses here
a_rec = {"type": "A",
@@ -56,5 +58,5 @@
"priority": 50,
"comment": "Backup mail server"}
recs = dom.add_records([a_rec, mx_rec])
-print recs
-print
+print(recs)
+print()
diff --git a/samples/cloud_dns/create_domain.py b/samples/cloud_dns/create_domain.py
index 3682e965..a3c5326a 100644
--- a/samples/cloud_dns/create_domain.py
+++ b/samples/cloud_dns/create_domain.py
@@ -16,6 +16,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+from __future__ import print_function
+
import os
import pyrax
@@ -32,5 +34,5 @@
dom = dns.create(name=domain_name, emailAddress="sample@example.edu",
ttl=900, comment="sample domain")
except exc.DomainCreationFailed as e:
- print "Domain creation failed:", e
-print "Domain created:", dom
+ print("Domain creation failed:", e)
+print("Domain created:", dom)
diff --git a/samples/cloud_dns/create_subdomain.py b/samples/cloud_dns/create_subdomain.py
index c777fb67..8f7c35c9 100644
--- a/samples/cloud_dns/create_subdomain.py
+++ b/samples/cloud_dns/create_subdomain.py
@@ -16,6 +16,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+from __future__ import print_function
+
import os
import sys
@@ -40,21 +42,21 @@
dom = dns.create(name=domain_name, emailAddress="sample@example.edu",
ttl=900, comment="sample domain")
except exc.DomainCreationFailed as e:
- print "Domain creation failed:", e
- print
+ print("Domain creation failed:", e)
+ print()
sys.exit()
- print "Domain created:", dom
- print
+ print("Domain created:", dom)
+ print()
sub_name = "sub.%s" % domain_name
try:
sub = dns.create(name=sub_name, emailAddress="sample@example.edu", ttl=900,
comment="sample subdomain")
except exc.DomainCreationFailed as e:
- print "Could not create '%s': %s" % (sub_name, e)
- print
+ print("Could not create '%s': %s" % (sub_name, e))
+ print()
sys.exit()
-print "Subdomain '%s' successfully created." % sub_name
-print sub
-print
+print("Subdomain '%s' successfully created." % sub_name)
+print(sub)
+print()
diff --git a/samples/cloud_dns/delete_all_ptr_records.py b/samples/cloud_dns/delete_all_ptr_records.py
index be88dd7e..d544410c 100644
--- a/samples/cloud_dns/delete_all_ptr_records.py
+++ b/samples/cloud_dns/delete_all_ptr_records.py
@@ -16,6 +16,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+from __future__ import print_function
+
import os
import sys
@@ -34,6 +36,6 @@
server = cs.servers.get(server_id)
ret = dns.delete_ptr_records(server)
-print
-print ret
-print
+print()
+print(ret)
+print()
diff --git a/samples/cloud_dns/delete_all_records.py b/samples/cloud_dns/delete_all_records.py
index ab222fc9..19b94b61 100644
--- a/samples/cloud_dns/delete_all_records.py
+++ b/samples/cloud_dns/delete_all_records.py
@@ -16,6 +16,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+from __future__ import print_function
+
import os
import sys
@@ -33,7 +35,7 @@
try:
dom = dns.find(name=domain_name)
except exc.NotFound:
- print "There is no DNS information for the domain '%s'." % domain_name
+ print("There is no DNS information for the domain '%s'." % domain_name)
sys.exit()
sub_iter = dns.get_record_iterator(dom)
@@ -45,11 +47,11 @@
count += 1
if not count:
- print "There were no non-NS records to delete."
+ print("There were no non-NS records to delete.")
else:
if count == 1:
- print "The one non-NS record for '%s' has been deleted." % domain_name
+ print("The one non-NS record for '%s' has been deleted." % domain_name)
else:
- print "All %s non-NS records for '%s' have been deleted." % (count,
- domain_name)
-print
+ print("All %s non-NS records for '%s' have been deleted." % (count,
+ domain_name))
+print()
diff --git a/samples/cloud_dns/delete_all_subdomains.py b/samples/cloud_dns/delete_all_subdomains.py
index d9b6f1c2..3c0cd046 100644
--- a/samples/cloud_dns/delete_all_subdomains.py
+++ b/samples/cloud_dns/delete_all_subdomains.py
@@ -16,6 +16,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+from __future__ import print_function
+
import os
import sys
@@ -33,7 +35,7 @@
try:
dom = dns.find(name=domain_name)
except exc.NotFound:
- print "There is no DNS information for the domain '%s'." % domain_name
+ print("There is no DNS information for the domain '%s'." % domain_name)
sys.exit()
sub_iter = dns.get_subdomain_iterator(dom)
@@ -42,10 +44,10 @@
count += 1
if not count:
- print "There were no subdomains to delete."
+ print("There were no subdomains to delete.")
else:
if count == 1:
- print "The one subdomain of '%s' has been deleted." % domain_name
+ print("The one subdomain of '%s' has been deleted." % domain_name)
else:
- print "All %s subdomains of '%s' have been deleted." % (count, domain_name)
-print
+ print("All %s subdomains of '%s' have been deleted." % (count, domain_name))
+print()
diff --git a/samples/cloud_dns/delete_domain.py b/samples/cloud_dns/delete_domain.py
index 039b0b5e..0a45c951 100644
--- a/samples/cloud_dns/delete_domain.py
+++ b/samples/cloud_dns/delete_domain.py
@@ -16,6 +16,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+from __future__ import print_function
+
import os
import sys
@@ -32,8 +34,8 @@
try:
dom = dns.find(name=domain_name)
except exc.NotFound:
- print "There is no DNS information for the domain '%s'." % domain_name
+ print("There is no DNS information for the domain '%s'." % domain_name)
sys.exit()
dom.delete()
-print "The domain '%s' was successfully deleted." % domain_name
+print("The domain '%s' was successfully deleted." % domain_name)
diff --git a/samples/cloud_dns/iterate_domains.py b/samples/cloud_dns/iterate_domains.py
index d04a7ea9..dd050aac 100644
--- a/samples/cloud_dns/iterate_domains.py
+++ b/samples/cloud_dns/iterate_domains.py
@@ -16,6 +16,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+from __future__ import print_function
+
import os
import pyrax
@@ -28,10 +30,10 @@
dns = pyrax.cloud_dns
def print_domain(domain):
- print "Domain:", domain.name
- print " email:", domain.emailAddress
- print " created:", domain.created
- print
+ print("Domain:", domain.name)
+ print(" email:", domain.emailAddress)
+ print(" created:", domain.created)
+ print()
count = 0
@@ -40,4 +42,4 @@ def print_domain(domain):
count += 1
print_domain(domain)
-print "There were a total of %s domain(s)." % count
+print("There were a total of %s domain(s)." % count)
diff --git a/samples/cloud_dns/list_domains.py b/samples/cloud_dns/list_domains.py
index eb4031ae..ade020e9 100644
--- a/samples/cloud_dns/list_domains.py
+++ b/samples/cloud_dns/list_domains.py
@@ -16,6 +16,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+from __future__ import print_function
+
import os
import pyrax
@@ -32,10 +34,10 @@
def print_domains(domains):
for domain in domains:
- print "Domain:", domain.name
- print " email:", domain.emailAddress
- print " created:", domain.created
- print
+ print("Domain:", domain.name)
+ print(" email:", domain.emailAddress)
+ print(" created:", domain.created)
+ print()
domains = dns.list(limit=PAGE_SIZE)
count += len(domains)
@@ -50,4 +52,4 @@ def print_domains(domains):
break
print_domains(domains)
-print "There were a total of %s domain(s)." % count
+print("There were a total of %s domain(s)." % count)
diff --git a/samples/cloud_dns/list_ptr_records.py b/samples/cloud_dns/list_ptr_records.py
index 310b6ccf..f935d586 100644
--- a/samples/cloud_dns/list_ptr_records.py
+++ b/samples/cloud_dns/list_ptr_records.py
@@ -16,6 +16,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+from __future__ import print_function
+
import os
import sys
@@ -36,12 +38,12 @@
ptr_records = dns.list_ptr_records(server)
if ptr_records:
for ptr_record in ptr_records:
- print "PTR Record:"
- print " ID:", ptr_record.id
- print " name:", ptr_record.name
- print " data:", ptr_record.data
- print " TTL:", ptr_record.ttl
- print " comment:", ptr_record.comment
+ print("PTR Record:")
+ print(" ID:", ptr_record.id)
+ print(" name:", ptr_record.name)
+ print(" data:", ptr_record.data)
+ print(" TTL:", ptr_record.ttl)
+ print(" comment:", ptr_record.comment)
else:
- print "There are no PTR records for device '%s'." % server
-print
+ print("There are no PTR records for device '%s'." % server)
+print()
diff --git a/samples/cloud_dns/list_records.py b/samples/cloud_dns/list_records.py
index ef915090..42eeab24 100644
--- a/samples/cloud_dns/list_records.py
+++ b/samples/cloud_dns/list_records.py
@@ -16,6 +16,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+from __future__ import print_function
+
import os
import sys
@@ -34,12 +36,12 @@
def print_records(records):
for record in records:
- print "Record:", record.type
- print " ID:", record.id
- print " data:", record.data
- print " TTL:", record.ttl
- print " comment:", record.comment
- print
+ print("Record:", record.type)
+ print(" ID:", record.id)
+ print(" data:", record.data)
+ print(" TTL:", record.ttl)
+ print(" comment:", record.comment)
+ print()
try:
dom = dns.find(name=domain_name)
@@ -52,9 +54,9 @@ def print_records(records):
dom = dns.create(name=domain_name, emailAddress="sample@example.edu",
ttl=900, comment="sample domain")
except exc.DomainCreationFailed as e:
- print "Domain creation failed:", e
- print "Domain created:", dom
- print
+ print("Domain creation failed:", e)
+ print("Domain created:", dom)
+ print()
records = dom.list_records(limit=PAGE_SIZE)
count += len(records)
@@ -69,5 +71,5 @@ def print_records(records):
break
print_records(records)
-print "There were a total of %s record(s)." % count
-print
+print("There were a total of %s record(s)." % count)
+print()
diff --git a/samples/cloud_dns/list_subdomains.py b/samples/cloud_dns/list_subdomains.py
index 5c7f25ad..adc984e3 100644
--- a/samples/cloud_dns/list_subdomains.py
+++ b/samples/cloud_dns/list_subdomains.py
@@ -16,6 +16,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+from __future__ import print_function
+
import os
import sys
@@ -34,10 +36,10 @@
def print_domains(domains):
for domain in domains:
- print "Domain:", domain.name
- print " email:", domain.emailAddress
- print " created:", domain.created
- print
+ print("Domain:", domain.name)
+ print(" email:", domain.emailAddress)
+ print(" created:", domain.created)
+ print()
try:
dom = dns.find(name=domain_name)
@@ -50,9 +52,9 @@ def print_domains(domains):
dom = dns.create(name=domain_name, emailAddress="sample@example.edu",
ttl=900, comment="sample domain")
except exc.DomainCreationFailed as e:
- print "Domain creation failed:", e
- print "Domain created:", dom
- print
+ print("Domain creation failed:", e)
+ print("Domain created:", dom)
+ print()
subdomains = dom.list_subdomains(limit=PAGE_SIZE)
count += len(subdomains)
@@ -67,6 +69,6 @@ def print_domains(domains):
break
print_domains(subdomains)
-print "There were a total of %s subdomain(s)." % count
+print("There were a total of %s subdomain(s)." % count)
subs = dom.list_subdomains()
-print subs
+print(subs)
diff --git a/samples/cloud_dns/update_domain.py b/samples/cloud_dns/update_domain.py
index 2baff996..0006e27a 100644
--- a/samples/cloud_dns/update_domain.py
+++ b/samples/cloud_dns/update_domain.py
@@ -16,6 +16,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+from __future__ import print_function
+
import os
import sys
@@ -32,12 +34,12 @@
try:
dom = dns.find(name=domain_name)
except exc.NotFound:
- print "There is no DNS information for the domain '%s'." % domain_name
+ print("There is no DNS information for the domain '%s'." % domain_name)
sys.exit()
-print "Original TTL for '%s': %s" % (domain_name, dom.ttl)
+print("Original TTL for '%s': %s" % (domain_name, dom.ttl))
# Add 10 minutes
new_ttl = dom.ttl + 600
dom.update(ttl=new_ttl)
dom.reload()
-print "New TTL: %s" % dom.ttl
+print("New TTL: %s" % dom.ttl)
diff --git a/samples/cloud_dns/update_ptr_record.py b/samples/cloud_dns/update_ptr_record.py
index 27830ec7..486b86bc 100644
--- a/samples/cloud_dns/update_ptr_record.py
+++ b/samples/cloud_dns/update_ptr_record.py
@@ -16,6 +16,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+from __future__ import print_function
+
import os
import sys
@@ -36,7 +38,7 @@
domain_name = "abc.example.edu"
records = dns.list_ptr_records(server)
if not records:
- print "There are no PTR records for device '%s' to update." % server
+ print("There are no PTR records for device '%s' to update." % server)
sys.exit()
rec = records[0]
orig_ttl = rec.ttl
@@ -47,8 +49,8 @@
data=orig_data, comment="TTL has been increased")
if resp:
- print "Original TTL:", orig_ttl
- print "New TTL:", new_ttl
+ print("Original TTL:", orig_ttl)
+ print("New TTL:", new_ttl)
else:
- print "Update failed."
-print
+ print("Update failed.")
+print()
diff --git a/samples/cloud_loadbalancers/add_remove_node.py b/samples/cloud_loadbalancers/add_remove_node.py
index e9db5d78..93da8dda 100644
--- a/samples/cloud_loadbalancers/add_remove_node.py
+++ b/samples/cloud_loadbalancers/add_remove_node.py
@@ -16,6 +16,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+from __future__ import print_function
+
import os
import time
@@ -28,11 +30,11 @@
clb = pyrax.cloud_loadbalancers
lb = clb.list()[0]
-print
-print "Load Balancer:", lb
-print
-print "Current nodes:", lb.nodes
-
+print()
+print("Load Balancer:", lb)
+print()
+print("Current nodes:", lb.nodes
+)
# You may have to adjust the address of the node to something on
# the same internal network as your load balancer.
new_node = clb.Node(address="10.177.1.2", port=80, condition="ENABLED")
@@ -40,18 +42,18 @@
pyrax.utils.wait_until(lb, "status", "ACTIVE", interval=1, attempts=30,
verbose=True)
-print
-print "After adding node:", lb.nodes
-
+print()
+print("After adding node:", lb.nodes
+)
# Now remove that node. Note that we can't use the original node instance,
# as it was created independently, and doesn't have the link to its load
# balancer. Instead, we'll get the last node from the load balancer.
added_node = [node for node in lb.nodes
if node.address == new_node.address][0]
-print
-print "Added Node:", added_node
+print()
+print("Added Node:", added_node)
added_node.delete()
pyrax.utils.wait_until(lb, "status", "ACTIVE", interval=1, attempts=30,
verbose=True)
-print
-print "After removing node:", lb.nodes
+print()
+print("After removing node:", lb.nodes)
diff --git a/samples/cloud_loadbalancers/content_caching.py b/samples/cloud_loadbalancers/content_caching.py
index 65e519cc..fd644a6b 100644
--- a/samples/cloud_loadbalancers/content_caching.py
+++ b/samples/cloud_loadbalancers/content_caching.py
@@ -16,6 +16,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+from __future__ import print_function
+
import os
import sys
@@ -29,17 +31,17 @@
try:
lb = clb.list()[0]
except IndexError:
- print "You do not have any load balancers yet."
- print "Please create one and then re-run this script."
+ print("You do not have any load balancers yet.")
+ print("Please create one and then re-run this script.")
sys.exit()
-print "Load Balancer:", lb
+print("Load Balancer:", lb)
orig = lb.content_caching
-print "Current setting of content caching:", orig
-print
+print("Current setting of content caching:", orig)
+print()
if orig:
- print "Turning off..."
+ print("Turning off...")
else:
- print "Turning on..."
+ print("Turning on...")
lb.content_caching = not orig
-print "New setting of content caching:", lb.content_caching
+print("New setting of content caching:", lb.content_caching)
diff --git a/samples/cloud_loadbalancers/create_lb.py b/samples/cloud_loadbalancers/create_lb.py
index 0cea9618..442bf2a9 100644
--- a/samples/cloud_loadbalancers/create_lb.py
+++ b/samples/cloud_loadbalancers/create_lb.py
@@ -16,6 +16,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+from __future__ import print_function
+
import os
import pyrax
@@ -31,7 +33,7 @@
vip = clb.VirtualIP(type="PUBLIC")
lb = clb.create(lb_name, port=80, protocol="HTTP", nodes=[node], virtual_ips=[vip])
-print "Node:", node.to_dict()
-print "Virtual IP:", vip.to_dict()
-print
-print "Load Balancer:", lb
+print("Node:", node.to_dict())
+print("Virtual IP:", vip.to_dict())
+print()
+print("Load Balancer:", lb)
diff --git a/samples/cloud_loadbalancers/create_node.py b/samples/cloud_loadbalancers/create_node.py
index cc0ca09e..ea913e40 100644
--- a/samples/cloud_loadbalancers/create_node.py
+++ b/samples/cloud_loadbalancers/create_node.py
@@ -16,6 +16,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+from __future__ import print_function
+
import os
import pyrax
@@ -26,8 +28,8 @@
# You need to specify an address, port and condition
node = clb.Node(address="10.1.1.1", port=80, condition="DISABLED")
-print "Node:", node
-
+print("Node:", node
+)
# Actually, 'condition' is optional; it will default to 'ENABLED'.
node_default = clb.Node(address="10.1.1.2", port=80)
-print "Node(using default condition):", node_default
+print("Node(using default condition):", node_default)
diff --git a/samples/cloud_loadbalancers/create_vip.py b/samples/cloud_loadbalancers/create_vip.py
index dda0eb9c..09676af2 100644
--- a/samples/cloud_loadbalancers/create_vip.py
+++ b/samples/cloud_loadbalancers/create_vip.py
@@ -15,6 +15,9 @@
# WARRANTIES 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 pyrax
@@ -31,7 +34,7 @@
# id: None
vip = clb.VirtualIP()
-print "Virtual IP (using defaults):", vip
-
+print("Virtual IP (using defaults):", vip
+)
vip = clb.VirtualIP(type="SERVICENET", address="1.2.3.4", ipVersion="IPV4", id=999)
-print "Virtual IP (using supplied values):", vip
+print("Virtual IP (using supplied values):", vip)
diff --git a/samples/cloud_loadbalancers/get_lb_attributes.py b/samples/cloud_loadbalancers/get_lb_attributes.py
index 212670f9..14a1a687 100644
--- a/samples/cloud_loadbalancers/get_lb_attributes.py
+++ b/samples/cloud_loadbalancers/get_lb_attributes.py
@@ -16,6 +16,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+from __future__ import print_function
+
import os
import sys
@@ -29,15 +31,15 @@
try:
lb = clb.list()[0]
except IndexError:
- print "You do not have any load balancers yet."
- print "Please create one and then re-run this script."
+ print("You do not have any load balancers yet.")
+ print("Please create one and then re-run this script.")
sys.exit()
-print "Load Balancer:", lb
-print "Name:", lb.name
-print "ID:", lb.id
-print "Status:", lb.status
-print "Nodes:", lb.nodes
-print "Virtual IPs:", lb.virtual_ips
-print "Algorithm:", lb.algorithm
-print "Protocol:", lb.protocol
+print("Load Balancer:", lb)
+print("Name:", lb.name)
+print("ID:", lb.id)
+print("Status:", lb.status)
+print("Nodes:", lb.nodes)
+print("Virtual IPs:", lb.virtual_ips)
+print("Algorithm:", lb.algorithm)
+print("Protocol:", lb.protocol)
diff --git a/samples/cloud_loadbalancers/get_usage.py b/samples/cloud_loadbalancers/get_usage.py
index 355c770c..657970ba 100644
--- a/samples/cloud_loadbalancers/get_usage.py
+++ b/samples/cloud_loadbalancers/get_usage.py
@@ -16,6 +16,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+from __future__ import print_function
+
import datetime
import os
@@ -28,22 +30,22 @@
# Get load balancer usage
usage = clb.get_usage()
-print "Usage for Account:", usage["accountId"]
-print
-print "Account Usage Records"
-print "-" * 30
+print("Usage for Account:", usage["accountId"])
+print()
+print("Account Usage Records")
+print("-" * 30)
au_recs = usage["accountUsage"]
for rec_key in au_recs.keys()[:5]:
recs = au_recs[rec_key]
if len(recs) > 5:
- print "(only the first 5 records...)"
- print recs[:5]
- print
-print "Load Balancer Usage Records"
-print "-" * 30
+ print("(only the first 5 records...)")
+ print(recs[:5])
+ print()
+print("Load Balancer Usage Records")
+print("-" * 30)
lb_recs = usage["loadBalancerUsages"]
if len(lb_recs) > 5:
- print "(only the first 5 records...)"
+ print("(only the first 5 records...)")
for rec in lb_recs[:5]:
- print rec
- print
+ print(rec)
+ print()
diff --git a/samples/cloud_loadbalancers/list_algorithms.py b/samples/cloud_loadbalancers/list_algorithms.py
index d4f089f7..6439e6cf 100644
--- a/samples/cloud_loadbalancers/list_algorithms.py
+++ b/samples/cloud_loadbalancers/list_algorithms.py
@@ -16,6 +16,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+from __future__ import print_function
+
import os
import pyrax
@@ -25,4 +27,4 @@
clb = pyrax.cloud_loadbalancers
# Get available algorithms
-print "Algorithms:", clb.algorithms
+print("Algorithms:", clb.algorithms)
diff --git a/samples/cloud_loadbalancers/list_protocols.py b/samples/cloud_loadbalancers/list_protocols.py
index 94c77085..74f6eab8 100644
--- a/samples/cloud_loadbalancers/list_protocols.py
+++ b/samples/cloud_loadbalancers/list_protocols.py
@@ -16,6 +16,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+from __future__ import print_function
+
import os
import pyrax
@@ -25,4 +27,4 @@
clb = pyrax.cloud_loadbalancers
# Get available protocols
-print "Protocols:", clb.protocols
+print("Protocols:", clb.protocols)
diff --git a/samples/cloud_loadbalancers/metadata.py b/samples/cloud_loadbalancers/metadata.py
index 1b5796c2..05e2553f 100644
--- a/samples/cloud_loadbalancers/metadata.py
+++ b/samples/cloud_loadbalancers/metadata.py
@@ -16,6 +16,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+from __future__ import print_function
+
import os
import pyrax
@@ -26,15 +28,15 @@
lb = clb.list()[0]
orig_meta = lb.get_metadata()
-print "Initial metadata:", orig_meta
+print("Initial metadata:", orig_meta)
lb.set_metadata({"a": "one", "b": "two", "c": "three"})
-print "New metadata:", lb.get_metadata()
+print("New metadata:", lb.get_metadata())
lb.update_metadata({"d": "four"})
-print "Updated metadata:", lb.get_metadata()
+print("Updated metadata:", lb.get_metadata())
lb.set_metadata({"e": "five"})
-print "After set_metadata:", lb.get_metadata()
+print("After set_metadata:", lb.get_metadata())
lb.delete_metadata()
-print "After delete_metadata:", lb.get_metadata()
+print("After delete_metadata:", lb.get_metadata())
if orig_meta:
lb.set_metadata(orig_meta)
- print "After restoring original metadata:", lb.get_metadata()
+ print("After restoring original metadata:", lb.get_metadata())
diff --git a/samples/cloud_loadbalancers/node_condition.py b/samples/cloud_loadbalancers/node_condition.py
index 8e628687..af91131e 100644
--- a/samples/cloud_loadbalancers/node_condition.py
+++ b/samples/cloud_loadbalancers/node_condition.py
@@ -16,6 +16,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+from __future__ import print_function
+
import os
import pyrax
@@ -26,12 +28,12 @@
lb = clb.list()[0]
# Initial state
-print "Initial:", [(node.id, node.condition) for node in lb.nodes]
-
+print("Initial:", [(node.id, node.condition) for node in lb.nodes]
+)
# Toggle the first node's condition between ENABLED and DISABLED
node = lb.nodes[0]
node.condition = "DISABLED" if node.condition == "ENABLED" else "ENABLED"
node.update()
# After toggling
-print "Toggled:", [(node.id, node.condition) for node in lb.nodes]
+print("Toggled:", [(node.id, node.condition) for node in lb.nodes])
diff --git a/samples/cloud_loadbalancers/session_persistence.py b/samples/cloud_loadbalancers/session_persistence.py
index 00f2da76..07925c40 100644
--- a/samples/cloud_loadbalancers/session_persistence.py
+++ b/samples/cloud_loadbalancers/session_persistence.py
@@ -16,6 +16,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+from __future__ import print_function
+
import os
import sys
@@ -29,18 +31,18 @@
try:
lb = clb.list()[0]
except IndexError:
- print "You do not have any load balancers yet."
- print "Please create one and then re-run this script."
+ print("You do not have any load balancers yet.")
+ print("Please create one and then re-run this script.")
sys.exit()
-print "Load Balancer:", lb
+print("Load Balancer:", lb)
orig = lb.session_persistence
-print "Current setting of session persistence:", orig or '""'
-print
+print("Current setting of session persistence:", orig or '""')
+print()
if orig:
- print "Clearing..."
+ print("Clearing...")
lb.session_persistence = ""
else:
- print "Setting persistence to HTTP_COOKIE..."
+ print("Setting persistence to HTTP_COOKIE...")
lb.session_persistence = "HTTP_COOKIE"
-print "New setting of session persistence:", lb.session_persistence or '""'
+print("New setting of session persistence:", lb.session_persistence or '""')
diff --git a/samples/cloud_loadbalancers/ssl_termination.py b/samples/cloud_loadbalancers/ssl_termination.py
index 054c3074..62688551 100644
--- a/samples/cloud_loadbalancers/ssl_termination.py
+++ b/samples/cloud_loadbalancers/ssl_termination.py
@@ -16,6 +16,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+from __future__ import print_function
+
import os
import sys
@@ -29,22 +31,22 @@
try:
lb = clb.list()[0]
except IndexError:
- print "You do not have any load balancers yet."
- print "Please create one and then re-run this script."
+ print("You do not have any load balancers yet.")
+ print("Please create one and then re-run this script.")
sys.exit()
orig = lb.get_ssl_termination()
-print "Current setting of SSL Termination:", orig
-print
+print("Current setting of SSL Termination:", orig)
+print()
if orig:
- print "Updating SSL Termination info..."
+ print("Updating SSL Termination info...")
curr_enabled = orig["enabled"]
new_enabled = not curr_enabled
lb.update_ssl_termination(enabled=new_enabled)
else:
- print "Adding SSL Termination info..."
+ print("Adding SSL Termination info...")
lb.add_ssl_termination(securePort=443, secureTrafficOnly=False,
certificate="dummy_certificate", privatekey="dummy_private_key")
-print
-print "New setting of SSL Termination:", lb.get_ssl_termination()
+print()
+print("New setting of SSL Termination:", lb.get_ssl_termination())
diff --git a/samples/cloud_monitoring/create_alarm.py b/samples/cloud_monitoring/create_alarm.py
index 8609fa58..9391df2b 100644
--- a/samples/cloud_monitoring/create_alarm.py
+++ b/samples/cloud_monitoring/create_alarm.py
@@ -16,6 +16,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+from __future__ import print_function
+
import os
import sys
@@ -33,15 +35,15 @@
# We need the IP address of the entity for this check
ents = cm.list_entities()
if not ents:
- print "You must create an entity before you can create a notification."
+ print("You must create an entity before you can create a notification.")
sys.exit()
-print "Select the entity on which you wish to create the notification:"
+print("Select the entity on which you wish to create the notification:")
ent = option_chooser(ents, attr="name")
entity = ents[ent]
-print entity
-
+print(entity
+)
checks = entity.list_checks()
-print "Select a check to notify about:"
+print("Select a check to notify about:")
check_num = option_chooser(checks, attr="label")
check = checks[check_num]
@@ -56,4 +58,4 @@
("if (rate(metric['average']) > 5) { return new AlarmStatus(WARNING); } "
"return new AlarmStatus(OK);"), label="sample alarm")
-print "Created Alarm %s" % alarm.id
+print("Created Alarm %s" % alarm.id)
diff --git a/samples/cloud_monitoring/create_check.py b/samples/cloud_monitoring/create_check.py
index 54268529..4be653d5 100644
--- a/samples/cloud_monitoring/create_check.py
+++ b/samples/cloud_monitoring/create_check.py
@@ -16,6 +16,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+from __future__ import print_function
+
import os
import sys
@@ -33,15 +35,15 @@
# We need the IP address of the entity for this check
ents = cm.list_entities()
if not ents:
- print "You must create an entity before you can create a notification."
+ print("You must create an entity before you can create a notification.")
sys.exit()
-print "Select the entity on which you wish to create the notification:"
+print("Select the entity on which you wish to create the notification:")
ent = option_chooser(ents, attr="name")
entity = ents[ent]
-print entity
-
+print(entity
+)
aliases = entity.ip_addresses.items()
-print "Select an IP address to check"
+print("Select an IP address to check")
interface = option_chooser(aliases)
alias = aliases[interface][0]
@@ -50,7 +52,7 @@
# List the available Monitoring Zones
zones = cm.list_monitoring_zones()
-print "Select a Monitoring Zone:"
+print("Select a Monitoring Zone:")
zone_choice = option_chooser(zones, attr="label")
zone = zones[zone_choice]
@@ -59,5 +61,5 @@
details={"count": 5}, monitoring_zones_poll=[zone],
period=60, timeout=20, target_alias=alias)
-print "Name:", chk.name
-print "ID:", chk.id
+print("Name:", chk.name)
+print("ID:", chk.id)
diff --git a/samples/cloud_monitoring/create_entity.py b/samples/cloud_monitoring/create_entity.py
index 5ee6df9b..5579aeb1 100644
--- a/samples/cloud_monitoring/create_entity.py
+++ b/samples/cloud_monitoring/create_entity.py
@@ -16,6 +16,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+from __future__ import print_function
+
import os
import sys
@@ -30,14 +32,14 @@
# Create an entity based on an existing server
servers = cs.servers.list()
if not servers:
- print "You must have at least one server to run this sample code."
+ print("You must have at least one server to run this sample code.")
exit()
server = servers[0]
ip = server.accessIPv4
ent = cm.create_entity(name="sample_entity", ip_addresses={"main": ip},
metadata={"note": "Sample enitity for server '%s'" % server.name})
-print "Name:", ent.name
-print "ID:", ent.id
-print "IPs:", ent.ip_addresses
-print "Meta:", ent.metadata
+print("Name:", ent.name)
+print("ID:", ent.id)
+print("IPs:", ent.ip_addresses)
+print("Meta:", ent.metadata)
diff --git a/samples/cloud_monitoring/create_notification.py b/samples/cloud_monitoring/create_notification.py
index 9e5aa094..c2538753 100644
--- a/samples/cloud_monitoring/create_notification.py
+++ b/samples/cloud_monitoring/create_notification.py
@@ -16,6 +16,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+from __future__ import print_function
+
import os
import sys
@@ -33,15 +35,15 @@
# We need the IP address of the entity for this check
ents = cm.list_entities()
if not ents:
- print "You must create an entity before you can create a notification."
+ print("You must create an entity before you can create a notification.")
sys.exit()
-print "Select the entity on which you wish to create the notification:"
+print("Select the entity on which you wish to create the notification:")
ent = option_chooser(ents, attr="name")
entity = ents[ent]
-print entity
-
+print(entity
+)
checks = entity.list_checks()
-print "Select a check to notify about:"
+print("Select a check to notify about:")
check_num = option_chooser(checks, attr="label")
check = checks[check_num]
@@ -59,5 +61,5 @@
np = cm.create_notification_plan(label="sample notification plan",
ok_state=notif, warning_state=notif, critical_state=notif)
-print "Created Notification %s" % notif.id
-print "Added %s to Notification Plan %s" % (notif.id, np.id)
+print("Created Notification %s" % notif.id)
+print("Added %s to Notification Plan %s" % (notif.id, np.id))
diff --git a/samples/cloud_monitoring/util.py b/samples/cloud_monitoring/util.py
index 2e917c20..a544c7cd 100644
--- a/samples/cloud_monitoring/util.py
+++ b/samples/cloud_monitoring/util.py
@@ -16,6 +16,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+from __future__ import print_function
+
import sys
def option_chooser(options, attr=None):
@@ -27,26 +29,24 @@ def option_chooser(options, attr=None):
"""
for num, option in enumerate(options):
if attr:
- print "%s: %s" % (num, getattr(option, attr))
+ print("%s: %s" % (num, getattr(option, attr)))
else:
- print "%s: %s" % (num, option)
-
+ print("%s: %s" % (num, option))
# Add an escape option
escape_opt = num + 1
- print "%s: I want to exit!" % escape_opt
-
+ print("%s: I want to exit!" % escape_opt)
choice = raw_input("Selection: ")
try:
ichoice = int(choice)
if ichoice > escape_opt:
raise ValueError
except ValueError:
- print "Valid entries are the numbers 0-%s. Received '%s'." % (escape_opt,
- choice)
+ print("Valid entries are the numbers 0-%s. Received '%s'." % (escape_opt,
+ choice))
sys.exit()
if ichoice == escape_opt:
- print "Bye!"
+ print("Bye!")
sys.exit()
return ichoice
diff --git a/samples/cloud_networks/create_bastion.py b/samples/cloud_networks/create_bastion.py
index 53c10d1c..96243a98 100644
--- a/samples/cloud_networks/create_bastion.py
+++ b/samples/cloud_networks/create_bastion.py
@@ -16,6 +16,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+from __future__ import print_function
+
from pprint import pprint
import os
@@ -37,23 +39,23 @@
# Create the new network
new_net = cnw.create(new_network_name, cidr=new_network_cidr)
-print "New network:", new_net
-
+print("New network:", new_net
+)
# Create the bastion server
networks = new_net.get_server_networks(public=True, private=True)
bastion = cs.servers.create("bastion", img_id, flavor_id,
nics=networks)
-print "Bastion server:", bastion.name, bastion.id
-
+print("Bastion server:", bastion.name, bastion.id
+)
# Create an isolated server
networks = new_net.get_server_networks(public=False, private=False)
isolated = cs.servers.create("isolated", img_id, flavor_id,
nics=networks)
-print "Isolated server:", isolated.name, isolated.id
-
-print
-print "The networks will not be visible until the servers have finished building."
-print "Do you want to wait until then to see the results? It might take several"
+print("Isolated server:", isolated.name, isolated.id
+)
+print()
+print("The networks will not be visible until the servers have finished building.")
+print("Do you want to wait until then to see the results? It might take several")
answer = raw_input("minutes to complete. [y/N]")
if answer not in "yY":
exit()
@@ -68,11 +70,11 @@
bastion = cs.servers.get(bas_id)
isolated = cs.servers.get(iso_id)
if "ERROR" in (bastion.status, isolated.status):
- print "There was an error building the servers. Please try again."
+ print("There was an error building the servers. Please try again.")
exit()
-print "Bastion server networks:"
+print("Bastion server networks:")
pprint(bastion.networks)
-print
-print "Isolated server networks:"
+print()
+print("Isolated server networks:")
pprint(isolated.networks)
diff --git a/samples/cloud_networks/create_network.py b/samples/cloud_networks/create_network.py
index f2a3ffed..34f46bf8 100644
--- a/samples/cloud_networks/create_network.py
+++ b/samples/cloud_networks/create_network.py
@@ -16,6 +16,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+from __future__ import print_function
+
import os
import pyrax
from pyrax import utils
@@ -30,9 +32,9 @@
# List initial status
nets = cnw.list()
for net in nets:
- print "Network: %s; cidr=%s; id=%s" % (net.label, net.cidr, net.id)
-print
+ print("Network: %s; cidr=%s; id=%s" % (net.label, net.cidr, net.id))
+print()
# Add the new network
new_net = cnw.create(new_network_name, cidr=new_network_cidr)
-print "NEW NET", new_net
+print("NEW NET", new_net)
diff --git a/samples/cloud_networks/delete_network.py b/samples/cloud_networks/delete_network.py
index 1832ba3f..4fbcc7ac 100644
--- a/samples/cloud_networks/delete_network.py
+++ b/samples/cloud_networks/delete_network.py
@@ -16,6 +16,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+from __future__ import print_function
+
import os
import pyrax
from pyrax import exc
@@ -36,11 +38,11 @@
except exc.NetworkNotFound:
msg = ("The sample network was not found. Please run the 'create_network' "
"script before running this script.")
- print msg
+ print(msg)
exit()
-print "Sample network:"
-print net
-print
+print("Sample network:")
+print(net)
+print()
net.delete()
-print "The network has been deleted."
+print("The network has been deleted.")
diff --git a/samples/cloudfiles/container_cdn.py b/samples/cloudfiles/container_cdn.py
index 5f94292e..82e49ce7 100644
--- a/samples/cloudfiles/container_cdn.py
+++ b/samples/cloudfiles/container_cdn.py
@@ -16,6 +16,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+from __future__ import print_function
+
import os
import pyrax
@@ -26,30 +28,30 @@
cont_name = pyrax.utils.random_name()
cont = cf.create_container(cont_name)
-print "Container:", cont
-print "Before Making Public"
-print "cdn_enabled", cont.cdn_enabled
-print "cdn_ttl", cont.cdn_ttl
-print "cdn_log_retention", cont.cdn_log_retention
-print "cdn_uri", cont.cdn_uri
-print "cdn_ssl_uri", cont.cdn_ssl_uri
-print "cdn_streaming_uri", cont.cdn_streaming_uri
-print "cdn_ios_uri", cont.cdn_ios_uri
-
+print("Container:", cont)
+print("Before Making Public")
+print("cdn_enabled", cont.cdn_enabled)
+print("cdn_ttl", cont.cdn_ttl)
+print("cdn_log_retention", cont.cdn_log_retention)
+print("cdn_uri", cont.cdn_uri)
+print("cdn_ssl_uri", cont.cdn_ssl_uri)
+print("cdn_streaming_uri", cont.cdn_streaming_uri)
+print("cdn_ios_uri", cont.cdn_ios_uri
+)
# Make it public
cont.make_public(ttl=1200)
# Now re-check the container's attributes
cont = cf.get_container(cont_name)
-print
-print "After Making Public"
-print "cdn_enabled", cont.cdn_enabled
-print "cdn_ttl", cont.cdn_ttl
-print "cdn_log_retention", cont.cdn_log_retention
-print "cdn_uri", cont.cdn_uri
-print "cdn_ssl_uri", cont.cdn_ssl_uri
-print "cdn_streaming_uri", cont.cdn_streaming_uri
-print "cdn_ios_uri", cont.cdn_ios_uri
-
+print()
+print("After Making Public")
+print("cdn_enabled", cont.cdn_enabled)
+print("cdn_ttl", cont.cdn_ttl)
+print("cdn_log_retention", cont.cdn_log_retention)
+print("cdn_uri", cont.cdn_uri)
+print("cdn_ssl_uri", cont.cdn_ssl_uri)
+print("cdn_streaming_uri", cont.cdn_streaming_uri)
+print("cdn_ios_uri", cont.cdn_ios_uri
+)
# clean up
cont.delete()
diff --git a/samples/cloudfiles/container_metadata.py b/samples/cloudfiles/container_metadata.py
index c8271a82..2a346009 100644
--- a/samples/cloudfiles/container_metadata.py
+++ b/samples/cloudfiles/container_metadata.py
@@ -16,6 +16,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+from __future__ import print_function
+
import os
import time
@@ -29,33 +31,33 @@
cont_name = pyrax.utils.random_name()
cont = cf.create_container(cont_name)
-print "Container:", cont
-
+print("Container:", cont
+)
# Get the existing metadata, if any
meta = cf.get_container_metadata(cont)
-print "Initial metadata:", meta
-
+print("Initial metadata:", meta
+)
# Create a dict of metadata. Make one key with the required prefix,
# and the other without, to illustrate how pyrax will 'massage'
# the keys to include the require prefix.
new_meta = {"X-Container-Meta-City": "Springfield",
"Famous_Family": "Simpsons"}
-print
-print "Setting container metadata to:", new_meta
+print()
+print("Setting container metadata to:", new_meta)
cf.set_container_metadata(cont, new_meta)
# Verify that the new metadata has been set for both keys.
meta = cf.get_container_metadata(cont)
-print "Updated metadata:", meta
-
+print("Updated metadata:", meta
+)
# Now remove the city key
-print
-print "Removing meta key for 'city'"
+print()
+print("Removing meta key for 'city'")
cf.remove_container_metadata_key(cont, "city")
# Verify that the key has been removed.
meta = cf.get_container_metadata(cont)
-print "After removing key:", meta
-
+print("After removing key:", meta
+)
# Clean up
cont.delete(True)
diff --git a/samples/cloudfiles/create_container.py b/samples/cloudfiles/create_container.py
index 5eeea116..2347fa9d 100644
--- a/samples/cloudfiles/create_container.py
+++ b/samples/cloudfiles/create_container.py
@@ -16,6 +16,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+from __future__ import print_function
+
import os
import pyrax
@@ -25,15 +27,15 @@
cf = pyrax.cloudfiles
cont_name = pyrax.utils.random_name(8)
-print "Creating container with random name:", cont_name
+print("Creating container with random name:", cont_name)
cont = cf.create_container(cont_name)
-print "New Container"
-print "Name:", cont.name
-print "# of objects:", cont.object_count
-print
-print "All Containers"
-print "list_containers:", cf.list_containers()
-print "get_all_containers:", cf.get_all_containers()
-
+print("New Container")
+print("Name:", cont.name)
+print("# of objects:", cont.object_count)
+print()
+print("All Containers")
+print("list_containers:", cf.list_containers())
+print("get_all_containers:", cf.get_all_containers()
+)
# Clean up
cont.delete()
diff --git a/samples/cloudfiles/delete_objects.py b/samples/cloudfiles/delete_objects.py
index c5261e91..2693e70f 100644
--- a/samples/cloudfiles/delete_objects.py
+++ b/samples/cloudfiles/delete_objects.py
@@ -16,6 +16,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+from __future__ import print_function
+
import os
import time
@@ -37,8 +39,8 @@
# Verify that it's there.
obj = cont.get_object(fname)
-print "Object present, size =", obj.total_bytes
-
+print("Object present, size =", obj.total_bytes
+)
# Delete it!
obj.delete()
start = time.time()
@@ -49,12 +51,12 @@
while obj:
try:
obj = cont.get_object(fname)
- print "...still there..."
+ print("...still there...")
time.sleep(0.5)
except exc.NoSuchObject:
obj = None
- print "Object '%s' has been deleted" % fname
- print "It took %4.2f seconds to appear as deleted." % (time.time() - start)
-
+ print("Object '%s' has been deleted" % fname)
+ print("It took %4.2f seconds to appear as deleted." % (time.time() - start)
+)
# Clean up
cont.delete(True)
diff --git a/samples/cloudfiles/fetch_objects.py b/samples/cloudfiles/fetch_objects.py
index 4a01ad26..bb75ec80 100644
--- a/samples/cloudfiles/fetch_objects.py
+++ b/samples/cloudfiles/fetch_objects.py
@@ -16,6 +16,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+from __future__ import print_function
+
import os
import pyrax
@@ -32,31 +34,31 @@
obj = cf.store_object(cont, obj_name, text)
# Make sure that the content stored is identical
-print "Using obj.get()"
+print("Using obj.get()")
stored_text = obj.get()
if stored_text == text:
- print "Stored text is identical"
+ print("Stored text is identical")
else:
- print "Difference detected!"
- print "Original:", text
- print "Stored:", stored_text
-
+ print("Difference detected!")
+ print("Original:", text)
+ print("Stored:", stored_text
+)
# Let's look at the metadata for the stored object
meta, stored_text = obj.get(include_meta=True)
-print
-print "Metadata:", meta
-
+print()
+print("Metadata:", meta
+)
# Demonstrate chunked retrieval
-print
-print "Using chunked retrieval"
+print()
+print("Using chunked retrieval")
obj_generator = obj.get(chunk_size=256)
joined_text = "".join(obj_generator)
if joined_text == text:
- print "Joined text is identical"
+ print("Joined text is identical")
else:
- print "Difference detected!"
- print "Original:", text
- print "Joined:", joined_text
-
+ print("Difference detected!")
+ print("Original:", text)
+ print("Joined:", joined_text
+)
# Clean up
cont.delete(True)
diff --git a/samples/cloudfiles/get_objects.py b/samples/cloudfiles/get_objects.py
index 30828e44..7ad391e2 100644
--- a/samples/cloudfiles/get_objects.py
+++ b/samples/cloudfiles/get_objects.py
@@ -16,8 +16,12 @@
# License for the specific language governing permissions and limitations
# under the License.
+from __future__ import print_function
+
import os
+import six
+
import pyrax
import pyrax.exceptions as exc
@@ -31,49 +35,49 @@
text = "File Content"
# Create 5 files with a similar name
-for i in xrange(5):
+for i in six.moves.range(5):
nm = "series_%s" % i
cont.store_object(nm, text)
# Create 5 files in a "folder", with repeated single-letter names
start = ord("a")
end = start + 5
-for i in xrange(start, end):
+for i in six.moves.range(start, end):
chars = chr(i) * 4
nm = "stuff/%s" % chars
cont.store_object(nm, text)
# Verify
objs = cont.get_objects()
-print
-print "Created the following objects:"
+print()
+print("Created the following objects:")
for obj in objs:
- print " ", obj.name
-print
+ print(" ", obj.name)
+print()
# Limit and marker
limit = 4
marker = ""
objs = cont.get_objects(limit=limit, marker=marker)
-print "Paging 4 objects at a time"
-print "Paged Objects:", [obj.name for obj in objs]
+print("Paging 4 objects at a time")
+print("Paged Objects:", [obj.name for obj in objs])
marker = objs[-1].name
while True:
objs = cont.get_objects(limit=limit, marker=marker)
if not objs:
break
- print "Paged Objects:", [obj.name for obj in objs]
+ print("Paged Objects:", [obj.name for obj in objs])
marker = objs[-1].name
-print
+print()
# Prefix
objs = cont.get_objects(prefix="stuff")
-print "Objects Prefixed with 'stuff':", [obj.name for obj in objs]
-print
+print("Objects Prefixed with 'stuff':", [obj.name for obj in objs])
+print()
# Delimiter
objs = cont.get_objects(delimiter="/")
-print "Objects Delimited with '/':", [obj.name for obj in objs]
-
+print("Objects Delimited with '/':", [obj.name for obj in objs]
+)
# Clean up
cont.delete(True)
diff --git a/samples/cloudfiles/object_metadata.py b/samples/cloudfiles/object_metadata.py
index 3f4ca3d0..6765cad8 100644
--- a/samples/cloudfiles/object_metadata.py
+++ b/samples/cloudfiles/object_metadata.py
@@ -16,6 +16,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+from __future__ import print_function
+
import os
import time
@@ -34,29 +36,29 @@
# Get the existing metadata, if any
meta = cf.get_object_metadata(cont, obj)
-print "Initial metadata:", meta
-
+print("Initial metadata:", meta
+)
# Create a dict of metadata. Make one key with the required prefix,
# and the other without, to illustrate how pyrax will 'massage'
# the keys to include the require prefix.
new_meta = {"X-Object-Meta-City": "Springfield",
"Famous_Family": "Simpsons"}
-print
-print "Adding metadata:", new_meta
+print()
+print("Adding metadata:", new_meta)
cf.set_object_metadata(cont, obj, new_meta)
# Verify that the new metadata has been set for both keys.
meta = cf.get_object_metadata(cont, obj)
-print "Updated metadata:", meta
-
+print("Updated metadata:", meta
+)
# Now remove the city key
-print
-print "Removing meta key for 'city'"
+print()
+print("Removing meta key for 'city'")
cf.remove_object_metadata_key(cont, obj, "city")
# Verify that the key has been removed.
meta = cf.get_object_metadata(cont, obj)
-print "After removing key:", meta
-
+print("After removing key:", meta
+)
# Clean up
cont.delete(True)
diff --git a/samples/cloudfiles/store_object.py b/samples/cloudfiles/store_object.py
index 3c2f508e..f13369cc 100644
--- a/samples/cloudfiles/store_object.py
+++ b/samples/cloudfiles/store_object.py
@@ -16,6 +16,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+from __future__ import print_function
+
import os
import pyrax
@@ -32,19 +34,19 @@
obj = cf.store_object(cont, obj_name, text)
# Verify that the object is there
-print "Stored Object Name:", obj.name
-print "Size:", obj.total_bytes
-
+print("Stored Object Name:", obj.name)
+print("Size:", obj.total_bytes
+)
# Make sure that the content stored is identical
stored_text = obj.get()
-print "Original text:", text
-print " Stored text:", stored_text
+print("Original text:", text)
+print(" Stored text:", stored_text)
if stored_text == text:
- print "Stored text is identical"
+ print("Stored text is identical")
else:
- print "Difference detected!"
- print "Original:", text
- print "Stored:", stored_text
-
+ print("Difference detected!")
+ print("Original:", text)
+ print("Stored:", stored_text
+)
# Clean up
cont.delete(True)
diff --git a/samples/cloudfiles/store_with_etag.py b/samples/cloudfiles/store_with_etag.py
index ac0c225f..5013a439 100644
--- a/samples/cloudfiles/store_with_etag.py
+++ b/samples/cloudfiles/store_with_etag.py
@@ -16,6 +16,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+from __future__ import print_function
+
import os
import pyrax
@@ -31,8 +33,8 @@
content = "This is a random collection of words."
chksum = pyrax.utils.get_checksum(content)
obj = cf.store_object(cont, obj_name, content, etag=chksum)
-print "Calculated checksum:", chksum
-print " Stored object etag:", obj.etag
-
+print("Calculated checksum:", chksum)
+print(" Stored object etag:", obj.etag
+)
# Clean up
cont.delete(True)
diff --git a/samples/cloudfiles/temporary_url.py b/samples/cloudfiles/temporary_url.py
index 4866e354..968d18d5 100644
--- a/samples/cloudfiles/temporary_url.py
+++ b/samples/cloudfiles/temporary_url.py
@@ -16,6 +16,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+from __future__ import print_function
+
import os
import requests
import time
@@ -38,10 +40,10 @@
Future raspberrypi exception 2to3. Dunder integration community goat import
jinja exception science. Kwargs integration diversity 2to3 dunder future
functools. Import integration itertools 2to3 cython pycon unit tuple."""
-print "Creating an object..."
+print("Creating an object...")
obj = cont.store_object(oname, ipsum)
-print "Getting the TempURL..."
+print("Getting the TempURL...")
# Get the existing TempURL key
curr_key = cf.get_temp_url_key()
if not curr_key:
@@ -50,16 +52,16 @@
# Create the Temporary URL
temp_url = obj.get_temp_url(seconds=60)
-print "Temporary URL"
-print temp_url
-print
+print("Temporary URL")
+print(temp_url)
+print()
# Now try downloading it
-print "Downloading the TempURL..."
+print("Downloading the TempURL...")
resp = requests.get(temp_url)
content = resp.content
-print "Downloaded content == stored content: ", content == ipsum
-
+print("Downloaded content == stored content: ", content == ipsum
+)
# Clean up
cf.set_temp_url_key(curr_key)
cont.delete(True)
diff --git a/samples/cloudfiles/upload_file.py b/samples/cloudfiles/upload_file.py
index d23725b2..e919520c 100644
--- a/samples/cloudfiles/upload_file.py
+++ b/samples/cloudfiles/upload_file.py
@@ -16,6 +16,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+from __future__ import print_function
+
import os
import pyrax
@@ -35,25 +37,25 @@
Last Line"""
# pyrax has a utility for creating temporary local files that clean themselves up.
with utils.SelfDeletingTempfile() as tmpname:
- print "Creating text file with the following content:"
- print "-" * 44
- print text
- print "-" * 44
+ print("Creating text file with the following content:")
+ print("-" * 44)
+ print(text)
+ print("-" * 44)
with open(tmpname, "w") as tmp:
tmp.write(text)
nm = os.path.basename(tmpname)
- print
- print "Uploading file: %s" % nm
+ print()
+ print("Uploading file: %s" % nm)
cf.upload_file(cont, tmpname, content_type="text/text")
# Let's verify that the file is there
obj = cont.get_object(nm)
-print
-print "Stored Object:", obj
-print "Retrieved Content:"
-print "-" * 44
+print()
+print("Stored Object:", obj)
+print("Retrieved Content:")
+print("-" * 44)
# Get the contents
-print obj.get()
-print "-" * 44
-
+print(obj.get())
+print("-" * 44
+)
# Clean up
cont.delete(True)
diff --git a/samples/cloudfiles/upload_folder.py b/samples/cloudfiles/upload_folder.py
index e694070c..4f8536be 100644
--- a/samples/cloudfiles/upload_folder.py
+++ b/samples/cloudfiles/upload_folder.py
@@ -16,9 +16,13 @@
# License for the specific language governing permissions and limitations
# under the License.
+from __future__ import print_function
+
import os
import time
+import six
+
import pyrax
import pyrax.exceptions as exc
import pyrax.utils as utils
@@ -35,7 +39,7 @@
# themselves up.
with utils.SelfDeletingTempDirectory() as tmpfolder:
# Create a bunch of files
- for idx in xrange(13):
+ for idx in six.moves.range(13):
fname = "file_%s" % idx
pth = os.path.join(tmpfolder, fname)
with open(pth, "w") as tmp:
@@ -45,7 +49,7 @@
subfolder_path = os.path.join(tmpfolder, "subfolder")
os.mkdir(subfolder_path)
# Create some files in the subfolder, too.
- for idx in xrange(7):
+ for idx in six.moves.range(7):
fname = "subfile_%s" % idx
pth = os.path.join(subfolder_path, fname)
with open(pth, "w") as tmp:
@@ -55,25 +59,25 @@
# named 'upfolder'. We'll have it skip all files ending in the digits
# '2', '6' or '0'.
ignore = ["*2", "*6", "*0"]
- print "Beginning Folder Uplaod"
+ print("Beginning Folder Uplaod")
upload_key, total_bytes = cf.upload_folder(tmpfolder, cont, ignore=ignore)
# Since upload_folder happens in the background, we need to stay in this
# block until the upload is complete, or the SelfDeletingTempDirectory
# will be deleted, and the upload won't find the files it needs.
- print "Total bytes to upload:", total_bytes
+ print("Total bytes to upload:", total_bytes)
uploaded = 0
while uploaded < total_bytes:
uploaded = cf.get_uploaded(upload_key)
- print "Progress: %4.2f%%" % ((uploaded * 100.0) / total_bytes)
+ print("Progress: %4.2f%%" % ((uploaded * 100.0) / total_bytes))
time.sleep(1)
# OK, the upload is complete. Let's verify what's in 'upfolder'.
folder_name = os.path.basename(tmpfolder)
-print
-print "Temp folder name:", folder_name
+print()
+print("Temp folder name:", folder_name)
nms = cf.get_container_object_names(cont, prefix=folder_name)
-print "Number of files in container:", len(nms)
-print "\n".join(nms)
-
+print("Number of files in container:", len(nms))
+print("\n".join(nms)
+)
# Clean up
cont.delete(True)
diff --git a/samples/cloudservers/create_image.py b/samples/cloudservers/create_image.py
index 686f86ee..71185a8f 100644
--- a/samples/cloudservers/create_image.py
+++ b/samples/cloudservers/create_image.py
@@ -16,6 +16,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+from __future__ import print_function
+
import os
import pyrax
@@ -25,20 +27,20 @@
cs = pyrax.cloudservers
servers = cs.servers.list()
srv_dict = {}
-print "Select a server from which an image will be created."
+print("Select a server from which an image will be created.")
for pos, srv in enumerate(servers):
- print "%s: %s" % (pos, srv.name)
+ print("%s: %s" % (pos, srv.name))
srv_dict[str(pos)] = srv.id
selection = None
while selection not in srv_dict:
if selection is not None:
- print " -- Invalid choice"
+ print(" -- Invalid choice")
selection = raw_input("Enter the number for your choice: ")
server_id = srv_dict[selection]
-print
+print()
nm = raw_input("Enter a name for the image: ")
img_id = cs.servers.create_image(server_id, nm)
-print "Image '%s' is being created. Its ID is: %s" % (nm, img_id)
+print("Image '%s' is being created. Its ID is: %s" % (nm, img_id))
diff --git a/samples/cloudservers/create_server.py b/samples/cloudservers/create_server.py
index 99996031..5b85e8a4 100644
--- a/samples/cloudservers/create_server.py
+++ b/samples/cloudservers/create_server.py
@@ -16,6 +16,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+from __future__ import print_function
+
import os
import pyrax
@@ -27,14 +29,13 @@
ubu_image = [img for img in cs.images.list()
if "12.04" in img.name][0]
-print "Ubuntu Image:", ubu_image
+print("Ubuntu Image:", ubu_image)
flavor_1GB = [flavor for flavor in cs.flavors.list()
if flavor.ram == 1024][0]
-print "1024 Flavor:", flavor_1GB
-
+print("1024 Flavor:", flavor_1GB)
server = cs.servers.create(server_name, ubu_image.id, flavor_1GB.id)
-print "Name:", server.name
-print "ID:", server.id
-print "Status:", server.status
-print "Admin Password:", server.adminPass
-print "Networks:", server.networks
+print("Name:", server.name)
+print("ID:", server.id)
+print("Status:", server.status)
+print("Admin Password:", server.adminPass)
+print("Networks:", server.networks)
diff --git a/samples/cloudservers/create_with_meta_and_files.py b/samples/cloudservers/create_with_meta_and_files.py
index 97f90e2b..5afdc2f3 100644
--- a/samples/cloudservers/create_with_meta_and_files.py
+++ b/samples/cloudservers/create_with_meta_and_files.py
@@ -16,6 +16,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+from __future__ import print_function
+
import os
import pyrax
@@ -42,12 +44,13 @@
server = cs.servers.create("meta_server", ubu_image.id, flavor_1GB.id,
meta=meta, files=files)
-print "Name:", server.name
-print "ID:", server.id
-print "Admin Password:", server.adminPass
-print "Metadata:", server.metadata
-print
-print "When the server becomes active, shell in as root with the admin password."
-print "Verify that the file '/root/testfile' exists, and contains the exact content"
-print "that was defined above."
-print
+print("Name:", server.name)
+print("ID:", server.id)
+print("Admin Password:", server.adminPass)
+print("Metadata:", server.metadata)
+print()
+print("When the server becomes active, shell in as root with the admin password.")
+print("Verify that the file '/root/testfile' exists, and contains the exact "
+ "content")
+print("that was defined above.")
+print()
diff --git a/samples/cloudservers/delete_image.py b/samples/cloudservers/delete_image.py
index 884f22ea..df00c239 100644
--- a/samples/cloudservers/delete_image.py
+++ b/samples/cloudservers/delete_image.py
@@ -16,6 +16,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+from __future__ import print_function
+
import os
import sys
@@ -28,20 +30,20 @@
all_images = cs.images.list()
images = [img for img in all_images if hasattr(img, "server")]
if not images:
- print "There are no images to delete. Create one, and then re-run this script."
- print
+ print("There are no images to delete. Create one, and then re-run this script.")
+ print()
sys.exit()
img_dict = {}
-print "Select an image to delete:"
+print("Select an image to delete:")
for pos, img in enumerate(images):
- print "%s: %s" % (pos, img.name)
+ print("%s: %s" % (pos, img.name))
img_dict[str(pos)] = img
selection = None
while selection not in img_dict:
if selection is not None:
- print " -- Invalid choice"
+ print(" -- Invalid choice")
selection = raw_input("Enter the number for your choice: ")
image = img_dict.get(selection)
cs.images.delete(image.id)
-print "Image '%s' has been deleted." % image.name
+print("Image '%s' has been deleted." % image.name)
diff --git a/samples/cloudservers/delete_server.py b/samples/cloudservers/delete_server.py
index ac9d2d82..b7c3a4f4 100644
--- a/samples/cloudservers/delete_server.py
+++ b/samples/cloudservers/delete_server.py
@@ -16,6 +16,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+from __future__ import print_function
+
import os
import sys
import time
@@ -28,46 +30,46 @@
cs = pyrax.cloudservers
def create_server():
- print "Creating the sacrificial server..."
+ print("Creating the sacrificial server...")
img = cs.list_images()[0]
flv = cs.list_flavors()[0]
srv = cs.servers.create("sacrifice", img.id, flv.id)
- print "Server '%s' created; ID=%s" % (srv.name, srv.id)
+ print("Server '%s' created; ID=%s" % (srv.name, srv.id))
return srv
-print
-print "Looking for a server named 'sacrifice' to delete..."
+print()
+print("Looking for a server named 'sacrifice' to delete...")
try:
sacrifice = cs.servers.find(name="sacrifice")
- print "Found server named 'sacrifice'."
+ print("Found server named 'sacrifice'.")
except Exception as e:
- print "No server named 'sacrifice' exists, so for safety reasons this"
- print "script will not do anything potentially destructive."
- print
+ print("No server named 'sacrifice' exists, so for safety reasons this")
+ print("script will not do anything potentially destructive.")
+ print()
answer = raw_input("Do you want to create that server now? [y/n] ")
if answer.strip().lower()[0] == "y":
sacrifice = create_server()
else:
- print "The server will not be created."
+ print("The server will not be created.")
sys.exit()
if sacrifice.status != "ACTIVE":
- print "Please wait until the 'sacrifice' server is in ACTIVE status."
- print "Current status:", sacrifice.status
+ print("Please wait until the 'sacrifice' server is in ACTIVE status.")
+ print("Current status:", sacrifice.status)
raw_answer = raw_input("Do you want this script to cycle every 10 seconds "
"to check? [y/n] ")
answer = raw_answer[0].lower()
if answer != "y":
sys.exit()
- print "Waiting... (press CTRL-C to stop)"
+ print("Waiting... (press CTRL-C to stop)")
while sacrifice.status != "ACTIVE":
time.sleep(10)
sacrifice = cs.servers.get(sacrifice.id)
- print "Status is '%s' at %s" % (sacrifice.status, time.ctime())
- print
- print "The server is now active. You may re-run this script to delete it."
+ print("Status is '%s' at %s" % (sacrifice.status, time.ctime()))
+ print()
+ print("The server is now active. You may re-run this script to delete it.")
sys.exit()
-print "Deleting 'sacrifice' server...",
+print("Deleting 'sacrifice' server...", end=' ')
sacrifice.delete()
-print " Done!"
+print(" Done!")
diff --git a/samples/cloudservers/list_flavors.py b/samples/cloudservers/list_flavors.py
index 9d8f0e7c..ec982ba4 100644
--- a/samples/cloudservers/list_flavors.py
+++ b/samples/cloudservers/list_flavors.py
@@ -16,6 +16,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+from __future__ import print_function
+
import os
import pyrax
@@ -26,9 +28,9 @@
flvs = cs.list_flavors()
for flv in flvs:
- print "Name:", flv.name
- print " ID:", flv.id
- print " RAM:", flv.ram
- print " Disk:", flv.disk
- print " VCPUs:", flv.vcpus
- print
+ print("Name:", flv.name)
+ print(" ID:", flv.id)
+ print(" RAM:", flv.ram)
+ print(" Disk:", flv.disk)
+ print(" VCPUs:", flv.vcpus)
+ print()
diff --git a/samples/cloudservers/list_images.py b/samples/cloudservers/list_images.py
index d13d4dfa..107a640f 100644
--- a/samples/cloudservers/list_images.py
+++ b/samples/cloudservers/list_images.py
@@ -16,6 +16,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+from __future__ import print_function
+
import os
import pyrax
@@ -26,4 +28,4 @@
imgs = cs.images.list()
for img in imgs:
- print "Name: %s\n ID: %s" % (img.name, img.id)
+ print("Name: %s\n ID: %s" % (img.name, img.id))
diff --git a/samples/cloudservers/reboot.py b/samples/cloudservers/reboot.py
index 34ed292c..253e5628 100644
--- a/samples/cloudservers/reboot.py
+++ b/samples/cloudservers/reboot.py
@@ -16,6 +16,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+from __future__ import print_function
+
import os
import sys
@@ -32,25 +34,26 @@
active = [server for server in servers
if server.status == "ACTIVE"][0]
except IndexError:
- print "There are no active servers in your account."
- print "Please create one before running this script."
+ print("There are no active servers in your account.")
+ print("Please create one before running this script.")
sys.exit()
# Display server info
-print "Server Name:", active.name
-print "Server ID:", active.id
-print "Server Status:", active.status
-print
+print("Server Name:", active.name)
+print("Server ID:", active.id)
+print("Server Status:", active.status)
+print()
answer = raw_input("Do you wish to reboot this server? [y/n] ")
if answer.strip().lower()[0] == "y":
- print
- print "A 'soft' reboot attempts a graceful shutdown and restart of your server."
- print "A 'hard' reboot power cycles your server."
+ print()
+ print("A 'soft' reboot attempts a graceful shutdown and restart of your "
+ "server.")
+ print("A 'hard' reboot power cycles your server.")
answer = raw_input("Which type of reboot do you want to do? [s/h] ")
answer = answer.strip().lower()[0]
reboot_type = {"s": "soft", "h": "hard"}[answer]
active.reboot(reboot_type)
# Reload the server
after_reboot = cs.servers.get(active.id)
- print
- print "After reboot command"
- print "Server Status =", after_reboot.status
+ print()
+ print("After reboot command")
+ print("Server Status =", after_reboot.status)
diff --git a/samples/images/add_image_member.py b/samples/images/add_image_member.py
new file mode 100644
index 00000000..7a32edd8
--- /dev/null
+++ b/samples/images/add_image_member.py
@@ -0,0 +1,62 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+# Copyright 2014 Rackspace
+
+# All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES 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 pyrax
+
+pyrax.set_setting("identity_type", "rackspace")
+creds_file = os.path.expanduser("~/.rackspace_cloud_credentials")
+pyrax.set_credential_file(creds_file)
+imgs = pyrax.images
+
+print("You will need a valid project_id for the member you wish to add.")
+images = imgs.list(visibility="private")
+
+if len(images) == 1:
+ image = images[0]
+ print("Only one image available; using '%s'." % image.name)
+else:
+ print("Images:")
+ for pos, image in enumerate(images):
+ print("[%s] - %s" % (pos, image.name))
+ snum = raw_input("Enter the number of the image you want to share: ")
+ if not snum:
+ exit()
+ try:
+ num = int(snum)
+ except ValueError:
+ print("'%s' is not a valid number." % snum)
+ exit()
+ if not 0 <= num < len(images):
+ print("'%s' is not a valid image number." % snum)
+ exit()
+ image = images[num]
+
+project_id = raw_input("Enter the project ID of the member you wish to share "
+ "this image with: ")
+if not project_id:
+ print("No project ID entered; exiting.")
+ exit()
+imgs.http_log_debug = True
+member = imgs.add_image_member(image, project_id)
+print("The following member was added:")
+print(" ID: %s" % member.id)
+print(" Status: %s" % member.status)
+print(" Created at: %s" % member.created_at)
diff --git a/samples/images/delete_image_member.py b/samples/images/delete_image_member.py
new file mode 100644
index 00000000..b7b669b4
--- /dev/null
+++ b/samples/images/delete_image_member.py
@@ -0,0 +1,72 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+# Copyright 2014 Rackspace
+
+# All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES 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 pyrax
+
+pyrax.set_setting("identity_type", "rackspace")
+creds_file = os.path.expanduser("~/.rackspace_cloud_credentials")
+pyrax.set_credential_file(creds_file)
+imgs = pyrax.images
+
+
+print("You will be able to remove members from an image (that is, unshare it)")
+images = imgs.list(visibility="private")
+
+images_with_members = []
+for image in images:
+ members = image.list_members()
+ if not members:
+ continue
+ images_with_members.append((image, members))
+
+if not images_with_members:
+ print("You have no images that are shared with other members.")
+ exit()
+
+member_index = 0
+to_delete = []
+for image, members in images_with_members:
+ print("Image: %s" % image.name)
+ for member in members:
+ print(" [%s] - %s (%s)" % (member_index, member.id, member.status))
+ to_delete.append(member)
+ member_index += 1
+snum = raw_input("Enter the number of the member you wish to delete: ")
+if not snum:
+ exit()
+try:
+ num = int(snum)
+except ValueError:
+ print("'%s' is not a valid number." % snum)
+ exit()
+if not 0 <= num < member_index:
+ print("'%s' is not a valid member number." % snum)
+ exit()
+member = to_delete[num]
+
+imgs.http_log_debug = True
+res = imgs.delete_image_member(member.image_id, member.id)
+
+print("RES", res)
+#print("The following member was added:")
+#print(" ID: %s" % member.id)
+#print(" Status: %s" % member.status)
+#print(" Created at: %s" % member.created_at)
diff --git a/samples/images/export_task.py b/samples/images/export_task.py
new file mode 100644
index 00000000..31cf82be
--- /dev/null
+++ b/samples/images/export_task.py
@@ -0,0 +1,75 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+# Copyright 2014 Rackspace
+
+# All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES 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 pyrax
+
+pyrax.set_setting("identity_type", "rackspace")
+creds_file = os.path.expanduser("~/.rackspace_cloud_credentials")
+pyrax.set_credential_file(creds_file)
+imgs = pyrax.images
+cf = pyrax.cloudfiles
+
+print("You will need to select an image to export, and a Container into which "
+ "the exported image will be placed.")
+images = imgs.list(visibility="private")
+print()
+print("Select an image to export:")
+for pos, image in enumerate(images):
+ print("[%s] %s" % (pos, image.name))
+snum = raw_input("Enter the number of the image you want to share: ")
+if not snum:
+ exit()
+try:
+ num = int(snum)
+except ValueError:
+ print("'%s' is not a valid number." % snum)
+ exit()
+if not 0 <= num < len(images):
+ print("'%s' is not a valid image number." % snum)
+ exit()
+image = images[num]
+
+conts = cf.list()
+print()
+print("Select the target container to place the exported image:")
+for pos, cont in enumerate(conts):
+ print("[%s] %s" % (pos, cont.name))
+snum = raw_input("Enter the number of the container: ")
+if not snum:
+ exit()
+try:
+ num = int(snum)
+except ValueError:
+ print("'%s' is not a valid number." % snum)
+ exit()
+if not 0 <= num < len(conts):
+ print("'%s' is not a valid container number." % snum)
+ exit()
+cont = conts[num]
+
+task = imgs.export_task(image, cont)
+print("Task ID=%s" % task.id)
+print()
+answer = raw_input("Do you want to track the task until completion? This may "
+ "take several minutes. [y/N]: ")
+if answer and answer[0].lower() == "y":
+ pyrax.utils.wait_until(task, "status", ["success", "failure"],
+ verbose=True, interval=30)
diff --git a/samples/images/import_task.py b/samples/images/import_task.py
new file mode 100644
index 00000000..5d26aeb1
--- /dev/null
+++ b/samples/images/import_task.py
@@ -0,0 +1,93 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+# Copyright 2014 Rackspace
+
+# All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES 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 pyrax
+
+pyrax.set_setting("identity_type", "rackspace")
+creds_file = os.path.expanduser("~/.rackspace_cloud_credentials")
+pyrax.set_credential_file(creds_file)
+imgs = pyrax.images
+cf = pyrax.cloudfiles
+
+print("You will need an image file stored in a Cloud Files container.")
+conts = cf.list()
+print()
+print("Select the container containing the image to import:")
+for pos, cont in enumerate(conts):
+ print("[%s] %s" % (pos, cont.name))
+snum = raw_input("Enter the number of the container: ")
+if not snum:
+ exit()
+try:
+ num = int(snum)
+except ValueError:
+ print("'%s' is not a valid number." % snum)
+ exit()
+if not 0 <= num < len(conts):
+ print("'%s' is not a valid container number." % snum)
+ exit()
+cont = conts[num]
+
+print()
+print("Select the image object:")
+objs = cont.get_objects()
+for pos, obj in enumerate(objs):
+ print("[%s] %s" % (pos, obj.name))
+snum = raw_input("Enter the number of the image object: ")
+if not snum:
+ exit()
+try:
+ num = int(snum)
+except ValueError:
+ print("'%s' is not a valid number." % snum)
+ exit()
+if not 0 <= num < len(conts):
+ print("'%s' is not a valid object number." % snum)
+ exit()
+obj = objs[num]
+
+fmt = raw_input("Enter the format of the image [VHD]: ")
+fmt = fmt or "VHD"
+base_name = os.path.splitext(os.path.basename(obj.name))[0]
+obj_name = raw_input("Enter a name for the imported image ['%s']: " % base_name)
+obj_name = obj_name or base_name
+
+task = imgs.import_task(obj, cont, img_format=fmt, img_name=obj_name)
+print("Task ID=%s" % task.id)
+print()
+answer = raw_input("Do you want to track the task until completion? This may "
+ "take several minutes. [y/N]: ")
+if answer and answer[0].lower() == "y":
+ pyrax.utils.wait_until(task, "status", ["success", "failure"],
+ verbose=True, interval=30)
+ print()
+ if task.status == "success":
+ print("Success!")
+ print("Your new image:")
+ new_img = imgs.find(name=obj_name)
+ print(" ID: %s" % new_img.id)
+ print(" Name: %s" % new_img.name)
+ print(" Status: %s" % new_img.status)
+ print(" Size: %s" % new_img.size)
+ print(" Tags: %s" % new_img.tags)
+ else:
+ print("Image import failed!")
+ print("Reason: %s" % task.message)
diff --git a/samples/images/list_image_members.py b/samples/images/list_image_members.py
new file mode 100644
index 00000000..a2337bf9
--- /dev/null
+++ b/samples/images/list_image_members.py
@@ -0,0 +1,42 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+# Copyright 2014 Rackspace
+
+# All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES 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 pyrax
+
+pyrax.set_setting("identity_type", "rackspace")
+creds_file = os.path.expanduser("~/.rackspace_cloud_credentials")
+pyrax.set_credential_file(creds_file)
+imgs = pyrax.images
+
+print("This will loop through all your private images and list the members for "
+ "each.")
+images = imgs.list(visibility="private")
+if not images:
+ print("No images exist.")
+ exit()
+for image in images:
+ members = imgs.list_image_members(image)
+ if not members:
+ print("Image %s: no members" % image.id)
+ else:
+ print("Image %s:" % image.id)
+ for member in members:
+ print(" %s (%s)" % (member.id, member.status))
diff --git a/samples/images/list_images.py b/samples/images/list_images.py
new file mode 100644
index 00000000..9c85e557
--- /dev/null
+++ b/samples/images/list_images.py
@@ -0,0 +1,36 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+# Copyright 2014 Rackspace
+
+# All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES 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 pyrax
+
+pyrax.set_setting("identity_type", "rackspace")
+creds_file = os.path.expanduser("~/.rackspace_cloud_credentials")
+pyrax.set_credential_file(creds_file)
+imgs = pyrax.images
+
+images = imgs.list()
+
+if not images:
+ print("No images exist.")
+ exit()
+print("There are %s images:" % len(images))
+for image in images:
+ print(" (%s) %s (ID=%s)" % (image.visibility, image.name, image.id))
diff --git a/samples/images/list_images_filtered.py b/samples/images/list_images_filtered.py
new file mode 100644
index 00000000..c1a1ad14
--- /dev/null
+++ b/samples/images/list_images_filtered.py
@@ -0,0 +1,57 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+# Copyright 2014 Rackspace
+
+# All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES 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 pyrax
+
+pyrax.set_setting("identity_type", "rackspace")
+creds_file = os.path.expanduser("~/.rackspace_cloud_credentials")
+pyrax.set_credential_file(creds_file)
+imgs = pyrax.images
+
+print("Filtering on visibility='private'")
+images = imgs.list(visibility="private")
+if not images:
+ print("No images exist.")
+ exit()
+print("There are %s images with visibility='private':" % len(images))
+for image in images:
+ print(" (%s) %s (ID=%s)" % (image.visibility, image.name, image.id))
+
+print("-" * 66)
+print("Filtering on name='Ubuntu 13.10 (Saucy Salamander)'")
+images = imgs.list(name="Ubuntu 13.10 (Saucy Salamander)")
+if not images:
+ print("No images exist.")
+ exit()
+print("There are %s images with name=Ubuntu 13.10 (Saucy Salamander):" %
+ len(images))
+for image in images:
+ print(" (%s) %s (ID=%s)" % (image.visibility, image.name, image.id))
+
+print("-" * 66)
+print("Filtering on size_min > 1000000000")
+images = imgs.list(size_min=1000000000)
+if not images:
+ print("No images exist.")
+ exit()
+print("There are %s images with size_min > 1000000000:" % len(images))
+for image in images:
+ print(" (%s) %s (ID=%s)" % (image.size, image.name, image.id))
diff --git a/samples/images/list_tasks.py b/samples/images/list_tasks.py
new file mode 100644
index 00000000..8ac0423f
--- /dev/null
+++ b/samples/images/list_tasks.py
@@ -0,0 +1,38 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+# Copyright 2014 Rackspace
+
+# All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES 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 pyrax
+
+pyrax.set_setting("identity_type", "rackspace")
+creds_file = os.path.expanduser("~/.rackspace_cloud_credentials")
+pyrax.set_credential_file(creds_file)
+imgs = pyrax.images
+
+print("This will loop through all current tasks.")
+tasks = imgs.list_tasks()
+for task in tasks:
+ print()
+ print("Task ID=%s" % task.id)
+ print(" Type: %s" % task.type)
+ print(" Status: %s" % task.status)
+ print(" Message: %s" % task.message)
+ print(" Created: %s" % task.created_at)
+ print(" Expires: %s" % task.expires_at)
diff --git a/samples/queueing/claim_messages.py b/samples/queueing/claim_messages.py
index d76a80dc..3e52a84d 100644
--- a/samples/queueing/claim_messages.py
+++ b/samples/queueing/claim_messages.py
@@ -16,6 +16,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+from __future__ import print_function
+
import os
import pyrax
import pyrax.exceptions as exc
@@ -27,16 +29,16 @@
queues = pq.list()
if not queues:
- print "There are no queues to post to. Please create one before proceeding."
+ print("There are no queues to post to. Please create one before proceeding.")
exit()
if len(queues) == 1:
queue = queues[0]
- print "Only one queue available; using '%s'." % queue.name
+ print("Only one queue available; using '%s'." % queue.name)
else:
- print "Queues:"
+ print("Queues:")
for pos, queue in enumerate(queues):
- print "%s - %s" % (pos, queue.name)
+ print("%s - %s" % (pos, queue.name))
snum = raw_input("Enter the number of the queue you wish to post a message "
"to: ")
if not snum:
@@ -44,16 +46,16 @@
try:
num = int(snum)
except ValueError:
- print "'%s' is not a valid number." % snum
+ print("'%s' is not a valid number." % snum)
exit()
if not 0 <= num < len(queues):
- print "'%s' is not a valid queue number." % snum
+ print("'%s' is not a valid queue number." % snum)
exit()
queue = queues[num]
sttl = raw_input("Enter a TTL for the claim: ")
if not sttl:
- print "A TTL value is required."
+ print("A TTL value is required.")
exit()
else:
try:
@@ -61,15 +63,15 @@
if not 60 <= ttl <= 43200:
old_ttl = ttl
ttl = max(min(ttl, 43200), 60)
- print ("TTL values must be between 60 and 43200 seconds; changing "
- "it to '%s'." % ttl)
+ print("TTL values must be between 60 and 43200 seconds; changing "
+ "it to '%s'." % ttl)
except ValueError:
- print "'%s' is not a valid number." % sttl
+ print("'%s' is not a valid number." % sttl)
exit()
sgrace = raw_input("Enter a grace period for the claim: ")
if not sgrace:
- print "A value for the grace period is required."
+ print("A value for the grace period is required.")
exit()
else:
try:
@@ -77,10 +79,10 @@
if not 60 <= grace <= 43200:
old_grace = grace
grace = max(min(grace, 43200), 60)
- print ("Grace values must be between 60 and 43200 seconds; changing "
- "it to '%s'." % grace)
+ print("Grace values must be between 60 and 43200 seconds; changing "
+ "it to '%s'." % grace)
except ValueError:
- print "'%s' is not a valid number." % sgrace
+ print("'%s' is not a valid number." % sgrace)
exit()
scount = raw_input("Enter the number of messages to claim (max=20), or press "
@@ -91,18 +93,18 @@
try:
count = int(scount)
except ValueError:
- print "'%s' is not a valid number." % scount
+ print("'%s' is not a valid number." % scount)
exit()
claim = pq.claim_messages(queue, ttl, grace, count=count)
if not claim:
- print "There were no messages available to claim."
+ print("There were no messages available to claim.")
exit()
num_msgs = len(claim.messages)
-print
-print "You have successfully claimed %s messages." % num_msgs
-print "Claim ID:", claim.id
+print()
+print("You have successfully claimed %s messages." % num_msgs)
+print("Claim ID:", claim.id)
for msg in claim.messages:
- print "Age:", msg.age
- print "Body:", msg.body
- print
+ print("Age:", msg.age)
+ print("Body:", msg.body)
+ print()
diff --git a/samples/queueing/create_queue.py b/samples/queueing/create_queue.py
index 27634ab3..193a9e7a 100644
--- a/samples/queueing/create_queue.py
+++ b/samples/queueing/create_queue.py
@@ -16,6 +16,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+from __future__ import print_function
+
import os
import pyrax
import pyrax.exceptions as exc
@@ -34,4 +36,4 @@
msg = "The queue '%s' has been created." % queue.name
except exc.DuplicateQueue:
msg = "A queue with the name '%s' already exists." % name
-print msg
+print(msg)
diff --git a/samples/queueing/delete_message.py b/samples/queueing/delete_message.py
index 14c03f80..bb435c51 100644
--- a/samples/queueing/delete_message.py
+++ b/samples/queueing/delete_message.py
@@ -16,6 +16,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+from __future__ import print_function
+
import os
import pyrax
import pyrax.exceptions as exc
@@ -27,16 +29,16 @@
queues = pq.list()
if not queues:
- print "There are no queues to post to. Please create one before proceeding."
+ print("There are no queues to post to. Please create one before proceeding.")
exit()
if len(queues) == 1:
queue = queues[0]
- print "Only one queue available; using '%s'." % queue.name
+ print("Only one queue available; using '%s'." % queue.name)
else:
- print "Queues:"
+ print("Queues:")
for pos, queue in enumerate(queues):
- print "%s - %s" % (pos, queue.name)
+ print("%s - %s" % (pos, queue.name))
snum = raw_input("Enter the number of the queue you wish to list messages "
"from: ")
if not snum:
@@ -44,33 +46,33 @@
try:
num = int(snum)
except ValueError:
- print "'%s' is not a valid number." % snum
+ print("'%s' is not a valid number." % snum)
exit()
if not 0 <= num < len(queues):
- print "'%s' is not a valid queue number." % snum
+ print("'%s' is not a valid queue number." % snum)
exit()
queue = queues[num]
echo = claimed = True
msgs = pq.list_messages(queue, echo=echo, include_claimed=claimed)
if not msgs:
- print "There are no messages available in this queue."
+ print("There are no messages available in this queue.")
exit()
for pos, msg in enumerate(msgs):
msg.get()
- print pos, "- ID:", msg.id, msg.claim_id, "Body='%s'" % msg.body[:80]
+ print(pos, "- ID:", msg.id, msg.claim_id, "Body='%s'" % msg.body[:80])
snum = raw_input("Enter the number of the message you wish to delete: ")
if not snum:
- print "No message selected; exiting."
+ print("No message selected; exiting.")
exit()
try:
num = int(snum)
except ValueError:
- print "'%s' is not a valid number." % snum
+ print("'%s' is not a valid number." % snum)
exit()
if not 0 <= num < len(msgs):
- print "'%s' is not a valid message number." % snum
+ print("'%s' is not a valid message number." % snum)
exit()
msg_to_delete = msgs[num]
msg_to_delete.delete()
-print
-print "The message has been deleted."
+print()
+print("The message has been deleted.")
diff --git a/samples/queueing/delete_messages.py b/samples/queueing/delete_messages.py
index 8f9b6590..726639bb 100644
--- a/samples/queueing/delete_messages.py
+++ b/samples/queueing/delete_messages.py
@@ -16,6 +16,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+from __future__ import print_function
+
import os
import pyrax
import pyrax.exceptions as exc
@@ -27,16 +29,16 @@
queues = pq.list()
if not queues:
- print "There are no queues to post to. Please create one before proceeding."
+ print("There are no queues to post to. Please create one before proceeding.")
exit()
if len(queues) == 1:
queue = queues[0]
- print "Only one queue available; using '%s'." % queue.name
+ print("Only one queue available; using '%s'." % queue.name)
else:
- print "Queues:"
+ print("Queues:")
for pos, queue in enumerate(queues):
- print "%s - %s" % (pos, queue.name)
+ print("%s - %s" % (pos, queue.name))
snum = raw_input("Enter the number of the queue you wish to list messages "
"from: ")
if not snum:
@@ -44,34 +46,34 @@
try:
num = int(snum)
except ValueError:
- print "'%s' is not a valid number." % snum
+ print("'%s' is not a valid number." % snum)
exit()
if not 0 <= num < len(queues):
- print "'%s' is not a valid queue number." % snum
+ print("'%s' is not a valid queue number." % snum)
exit()
queue = queues[num]
echo = claimed = True
msgs = pq.list_messages(queue, echo=echo, include_claimed=claimed)
if not msgs:
- print "There are no messages available in this queue."
+ print("There are no messages available in this queue.")
exit()
for pos, msg in enumerate(msgs):
msg.get()
- print pos, "- ID:", msg.id, msg.claim_id, "Body='%s'" % msg.body[:80]
+ print(pos, "- ID:", msg.id, msg.claim_id, "Body='%s'" % msg.body[:80])
snums = raw_input("Enter one or more numbers of the messages you wish to "
"delete, separated by spaces: ")
if not snums:
- print "No messages selected; exiting."
+ print("No messages selected; exiting.")
exit()
nums = [int(num) for num in snums.split()]
ids = [msg.id for msg in msgs if msgs.index(msg) in nums]
if not ids:
- print "No messages match your selections; exiting."
+ print("No messages match your selections; exiting.")
exit()
-print "DEL", pq.delete_messages_by_ids(queue, ids)
+print("DEL", pq.delete_messages_by_ids(queue, ids))
del_msgs = [msg for msg in msgs if msg.id in ids]
-print
-print "The following messages were deleted:"
+print()
+print("The following messages were deleted:")
for del_msg in del_msgs:
- print del_msg.id, "Body='%s'" % del_msg.body
+ print(del_msg.id, "Body='%s'" % del_msg.body)
diff --git a/samples/queueing/delete_queue.py b/samples/queueing/delete_queue.py
index 847fef6d..4e01b03d 100644
--- a/samples/queueing/delete_queue.py
+++ b/samples/queueing/delete_queue.py
@@ -16,6 +16,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+from __future__ import print_function
+
import os
import pyrax
import pyrax.exceptions as exc
@@ -27,22 +29,22 @@
queues = pq.list()
if not queues:
- print "There are no queues to delete."
+ print("There are no queues to delete.")
exit()
-print "Queues:"
+print("Queues:")
for pos, queue in enumerate(queues):
- print "%s - %s" % (pos, queue.name)
+ print("%s - %s" % (pos, queue.name))
snum = raw_input("Enter the number of the queue to delete: ")
if not snum:
exit()
try:
num = int(snum)
except ValueError:
- print "'%s' is not a valid number." % snum
+ print("'%s' is not a valid number." % snum)
exit()
if not 0 <= num < len(queues):
- print "'%s' is not a valid queue number." % snum
+ print("'%s' is not a valid queue number." % snum)
exit()
pq.delete(queues[num])
-print "Queue '%s' has been deleted." % queue.name
+print("Queue '%s' has been deleted." % queue.name)
diff --git a/samples/queueing/list_claims.py b/samples/queueing/list_claims.py
index ed2b9672..a656d40d 100644
--- a/samples/queueing/list_claims.py
+++ b/samples/queueing/list_claims.py
@@ -16,12 +16,14 @@
# License for the specific language governing permissions and limitations
# under the License.
+from __future__ import print_function
+
import os
import pyrax
import pyrax.exceptions as exc
-print "Sorry, this hasn't been implemented yet."
+print("Sorry, this hasn't been implemented yet.")
exit()
pyrax.set_setting("identity_type", "rackspace")
@@ -31,16 +33,16 @@
queues = pq.list()
if not queues:
- print "There are no queues to post to. Please create one before proceeding."
+ print("There are no queues to post to. Please create one before proceeding.")
exit()
if len(queues) == 1:
queue = queues[0]
- print "Only one queue available; using '%s'." % queue.name
+ print("Only one queue available; using '%s'." % queue.name)
else:
- print "Queues:"
+ print("Queues:")
for pos, queue in enumerate(queues):
- print "%s - %s" % (pos, queue.name)
+ print("%s - %s" % (pos, queue.name))
snum = raw_input("Enter the number of the queue you wish to list messages "
"from: ")
if not snum:
@@ -48,17 +50,17 @@
try:
num = int(snum)
except ValueError:
- print "'%s' is not a valid number." % snum
+ print("'%s' is not a valid number." % snum)
exit()
if not 0 <= num < len(queues):
- print "'%s' is not a valid queue number." % snum
+ print("'%s' is not a valid queue number." % snum)
exit()
queue = queues[num]
claims = pq.list_claims(queue)
if not claims:
- print "There are no claims available in this queue."
+ print("There are no claims available in this queue.")
exit()
for claim in claims:
- print "ID:", claim.id
- print claim
- print
+ print("ID:", claim.id)
+ print(claim)
+ print()
diff --git a/samples/queueing/list_messages.py b/samples/queueing/list_messages.py
index 05c2fd02..bcf322e1 100644
--- a/samples/queueing/list_messages.py
+++ b/samples/queueing/list_messages.py
@@ -16,6 +16,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+from __future__ import print_function
+
import os
import pyrax
import pyrax.exceptions as exc
@@ -27,16 +29,16 @@
queues = pq.list()
if not queues:
- print "There are no queues to post to. Please create one before proceeding."
+ print("There are no queues to post to. Please create one before proceeding.")
exit()
if len(queues) == 1:
queue = queues[0]
- print "Only one queue available; using '%s'." % queue.name
+ print("Only one queue available; using '%s'." % queue.name)
else:
- print "Queues:"
+ print("Queues:")
for pos, queue in enumerate(queues):
- print "%s - %s" % (pos, queue.name)
+ print("%s - %s" % (pos, queue.name))
snum = raw_input("Enter the number of the queue you wish to list messages "
"from: ")
if not snum:
@@ -44,10 +46,10 @@
try:
num = int(snum)
except ValueError:
- print "'%s' is not a valid number." % snum
+ print("'%s' is not a valid number." % snum)
exit()
if not 0 <= num < len(queues):
- print "'%s' is not a valid queue number." % snum
+ print("'%s' is not a valid queue number." % snum)
exit()
queue = queues[num]
echo = claimed = False
@@ -60,12 +62,12 @@
msgs = pq.list_messages(queue, echo=echo, include_claimed=claimed)
if not msgs:
- print "There are no messages available in this queue."
+ print("There are no messages available in this queue.")
exit()
for msg in msgs:
- print "ID:", msg.id
- print "Age:", msg.age
- print "TTL:", msg.ttl
- print "Claim ID:", msg.claim_id
- print "Body:", msg.body
- print
+ print("ID:", msg.id)
+ print("Age:", msg.age)
+ print("TTL:", msg.ttl)
+ print("Claim ID:", msg.claim_id)
+ print("Body:", msg.body)
+ print()
diff --git a/samples/queueing/list_queues.py b/samples/queueing/list_queues.py
index c740f1ea..8788e1f7 100644
--- a/samples/queueing/list_queues.py
+++ b/samples/queueing/list_queues.py
@@ -16,6 +16,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+from __future__ import print_function
+
import os
import pyrax
@@ -26,12 +28,12 @@
queues = pq.list()
if not queues:
- print "No queues have been created."
+ print("No queues have been created.")
exit()
num_queues = len(queues)
if num_queues == 1:
- print "There is one queue defined:"
+ print("There is one queue defined:")
else:
- print "There are %s queueis defined:" % num_queues
+ print("There are %s queueis defined:" % num_queues)
for queue in queues:
- print " %s" % queue.name
+ print(" %s" % queue.name)
diff --git a/samples/queueing/post_message.py b/samples/queueing/post_message.py
index 8f25cdde..8d6f583c 100644
--- a/samples/queueing/post_message.py
+++ b/samples/queueing/post_message.py
@@ -16,6 +16,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+from __future__ import print_function
+
import os
import pyrax
import pyrax.exceptions as exc
@@ -27,16 +29,16 @@
queues = pq.list()
if not queues:
- print "There are no queues to post to. Please create one before proceeding."
+ print("There are no queues to post to. Please create one before proceeding.")
exit()
if len(queues) == 1:
queue = queues[0]
- print "Only one queue available; using '%s'." % queue.name
+ print("Only one queue available; using '%s'." % queue.nam)
else:
- print "Queues:"
+ print("Queues:")
for pos, queue in enumerate(queues):
- print "%s - %s" % (pos, queue.name)
+ print("%s - %s" % (pos, queue.name))
snum = raw_input("Enter the number of the queue you wish to post a message "
"to: ")
if not snum:
@@ -44,10 +46,10 @@
try:
num = int(snum)
except ValueError:
- print "'%s' is not a valid number." % snum
+ print("'%s' is not a valid number." % snu)
exit()
if not 0 <= num < len(queues):
- print "'%s' is not a valid queue number." % snum
+ print("'%s' is not a valid queue number." % snu)
exit()
queue = queues[num]
msg = raw_input("Enter the message to post: ")
@@ -59,7 +61,7 @@
try:
ttl = int(sttl)
except ValueError:
- print "'%s' is not a valid number." % sttl
+ print("'%s' is not a valid number." % stt)
exit()
pq.post_message(queue, msg, ttl=ttl)
-print "Your message has been posted."
+print("Your message has been posted.")
diff --git a/setup.py b/setup.py
index 45c8accd..7b3bf599 100755
--- a/setup.py
+++ b/setup.py
@@ -38,6 +38,7 @@
"httplib2",
"keyring",
"requests>=1.0.0",
+ "six",
] + testing_requires,
packages=[
"pyrax",
diff --git a/tests/integrated/smoketest.py b/tests/integrated/smoketest.py
index 36e396f2..5278af12 100644
--- a/tests/integrated/smoketest.py
+++ b/tests/integrated/smoketest.py
@@ -1,6 +1,8 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
+from __future__ import print_function
+
try:
import eventlet
eventlet.patcher.monkey_patch(all=False, socket=True, time=True,
@@ -47,28 +49,28 @@ def __init__(self, region):
def auth(self, region):
# Make sure that keyring has been set up with the account credentials.
- print "Authenticating for region '%s'..." % region
+ print("Authenticating for region '%s'..." % region)
try:
pyrax.keyring_auth(region=region)
- print "Success!"
+ print("Success!")
except Exception as e:
- print "FAIL!", e
+ print("FAIL!", e)
self.failures.append("AUTHENTICATION")
- print
+ print()
def check_services(self):
for service in self.services:
- print "SERVICE:", service["name"],
+ print("SERVICE:", service["name"], end=' ')
if service["service"]:
- print "Success!"
+ print("Success!")
else:
- print "FAIL!"
+ print("FAIL!")
self.failures.append("Service=%s" % service["name"])
- print
+ print()
def run_tests(self):
if self.cs:
- print "Running 'compute' tests..."
+ print("Running 'compute' tests...")
self.cs_list_flavors()
self.cs_list_images()
self.cs_create_server()
@@ -76,25 +78,25 @@ def run_tests(self):
self.cs_list_servers()
if self.cnw:
- print "Running 'network' tests..."
+ print("Running 'network' tests...")
try:
self.cnw_create_network()
self.cnw_list_networks()
except exc.NotFound:
# Networking not supported
- print " - Networking not supported."
+ print(" - Networking not supported.")
except exc.NetworkCountExceeded:
- print " - Too many networks already exist."
+ print(" - Too many networks already exist.")
if self.cdb:
- print "Running 'database' tests..."
+ print("Running 'database' tests...")
self.cdb_list_flavors()
self.cdb_create_instance()
self.cdb_create_db()
self.cdb_create_user()
if self.cf:
- print "Running 'object_store' tests..."
+ print("Running 'object_store' tests...")
self.cf_create_container()
self.cf_list_containers()
self.cf_make_container_public()
@@ -102,19 +104,19 @@ def run_tests(self):
self.cf_upload_file()
if self.clb:
- print "Running 'load_balancer' tests..."
+ print("Running 'load_balancer' tests...")
self.lb_list()
self.lb_create()
if self.dns:
- print "Running 'DNS' tests..."
+ print("Running 'DNS' tests...")
self.dns_list()
self.dns_create_domain()
self.dns_create_record()
if self.cmn:
if not self.smoke_server:
- print "Server not available; skipping Monitoring tests."
+ print("Server not available; skipping Monitoring tests.")
return
self.cmn_create_entity()
self.cmn_list_check_types()
@@ -127,60 +129,60 @@ def run_tests(self):
## Specific tests start here ##
def cs_list_flavors(self):
- print "Listing Flavors:",
+ print("Listing Flavors:", end=' ')
self.cs_flavors = self.cs.list_flavors()
if self.cs_flavors:
- print
+ print()
for flavor in self.cs_flavors:
- print " -", flavor
+ print(" -", flavor)
else:
- print "FAIL!"
+ print("FAIL!")
self.failures.append("FLAVORS")
- print
+ print()
def cs_list_images(self):
- print "Listing Images:",
+ print("Listing Images:", end=' ')
self.cs_images = self.cs.list_base_images()
if self.cs_images:
- print
+ print()
for image in self.cs_images:
- print " -", image
+ print(" -", image)
else:
- print "FAIL!"
+ print("FAIL!")
self.failures.append("IMAGES")
- print
+ print()
def cnw_create_network(self):
- print "Creating network..."
+ print("Creating network...")
new_network_name = "SMOKETEST_NW"
new_network_cidr = "192.168.0.0/24"
- print "CREATE NETWORK:",
+ print("CREATE NETWORK:", end=' ')
self.smoke_network = self.cnw.create(new_network_name,
cidr=new_network_cidr)
self.cleanup_items.append(self.smoke_network)
if self.smoke_network:
- print "Success!"
+ print("Success!")
else:
- print "FAIL!"
+ print("FAIL!")
self.failures.append("CREATE NETWORK")
- print
+ print()
def cnw_list_networks(self):
- print "Listing networks..."
+ print("Listing networks...")
try:
networks = self.cnw.list()
except exc.NotFound:
# Many non-rax system do no support networking.
- print "Networking not available"
+ print("Networking not available")
return
for network in networks:
- print " - %s: %s (%s)" % (network.id, network.name, network.cidr)
+ print(" - %s: %s (%s)" % (network.id, network.name, network.cidr))
if not networks:
self.failures.append("LIST NETWORKS")
- print
+ print()
def cs_create_server(self):
- print "Creating server..."
+ print("Creating server...")
img = [img for img in self.cs_images
if "12.04" in img.name][0]
flavor = self.cs_flavors[0]
@@ -191,58 +193,58 @@ def cs_create_server(self):
["ACTIVE", "ERROR"], interval=10, verbose=True,
verbose_atts="progress")
if self.smoke_server.status == "ERROR":
- print "Server creation failed!"
+ print("Server creation failed!")
self.failures.append("SERVER CREATION")
else:
- print "Success!"
- print
+ print("Success!")
+ print()
def cs_reboot_server(self):
- print "Rebooting server..."
+ print("Rebooting server...")
self.smoke_server.reboot()
self.smoke_server = pyrax.utils.wait_until(self.smoke_server, "status",
["ACTIVE", "ERROR"], interval=10, verbose=True,
verbose_atts="progress")
if self.smoke_server.status == "ERROR":
- print "Server reboot failed!"
+ print("Server reboot failed!")
self.failures.append("SERVER REBOOT")
else:
- print "Success!"
- print
+ print("Success!")
+ print()
def cs_list_servers(self):
- print "Listing servers..."
+ print("Listing servers...")
servers = self.cs.servers.list()
if not servers:
- print "Server listing failed!"
+ print("Server listing failed!")
self.failures.append("SERVER LISTING")
else:
for server in servers:
- print " -", server.id, server.name
- print
+ print(" -", server.id, server.name)
+ print()
def cdb_list_flavors(self):
- print "Listing Database Flavors:",
+ print("Listing Database Flavors:", end=' ')
try:
self.cdb_flavors = self.cdb.list_flavors()
except Exception as e:
self.cdb_flavors = None
if self.cdb_flavors:
- print
+ print()
for flavor in self.cdb_flavors:
- print " -", flavor
+ print(" -", flavor)
else:
- print "FAIL!"
+ print("FAIL!")
self.failures.append("DB FLAVORS")
- print
+ print()
def cdb_create_instance(self):
if not self.cdb_flavors:
# Skip this test
- print "Skipping database instance creation..."
+ print("Skipping database instance creation...")
self.smoke_instance = None
return
- print "Creating database instance..."
+ print("Creating database instance...")
self.smoke_instance = self.cdb.create("SMOKETEST_DB_INSTANCE",
flavor=self.cdb_flavors[0], volume=1)
self.cleanup_items.append(self.smoke_instance)
@@ -250,91 +252,91 @@ def cdb_create_instance(self):
"status", ["ACTIVE", "ERROR"], interval=10, verbose=True,
verbose_atts="progress")
if self.smoke_instance.status == "ACTIVE":
- print "Success!"
+ print("Success!")
else:
- print "FAIL!"
+ print("FAIL!")
self.failures.append("DB INSTANCE CREATION")
- print
+ print()
def cdb_create_db(self):
if not self.smoke_instance:
# Skip this test
- print "Skipping database creation..."
+ print("Skipping database creation...")
return
- print "Creating database..."
+ print("Creating database...")
self.smoke_db = self.smoke_instance.create_database("SMOKETEST_DB")
self.cleanup_items.append(self.smoke_db)
dbs = self.smoke_instance.list_databases()
if self.smoke_db in dbs:
- print "Success!"
+ print("Success!")
else:
- print "FAIL!"
+ print("FAIL!")
self.failures.append("DB DATABASE CREATION")
- print
+ print()
def cdb_create_user(self):
if not self.smoke_instance:
# Skip this test
- print "Skipping database user creation..."
+ print("Skipping database user creation...")
return
- print "Creating database user..."
+ print("Creating database user...")
self.smoke_user = self.smoke_instance.create_user("SMOKETEST_USER",
"SMOKETEST_PW", database_names=[self.smoke_db])
self.cleanup_items.append(self.smoke_user)
users = self.smoke_instance.list_users()
if self.smoke_user in users:
- print "Success!"
+ print("Success!")
else:
- print "FAIL!"
+ print("FAIL!")
self.failures.append("DB USER CREATION")
- print
+ print()
def cf_create_container(self):
- print "Creating a Cloud Files Container..."
+ print("Creating a Cloud Files Container...")
self.smoke_cont = self.cf.create_container("SMOKETEST_CONTAINER")
self.cleanup_items.append(self.smoke_cont)
if self.smoke_cont:
- print "Success!"
+ print("Success!")
else:
- print "FAIL!"
+ print("FAIL!")
self.failures.append("CONTAINER CREATION")
- print
+ print()
def cf_list_containers(self):
- print "Listing the Cloud Files Containers..."
+ print("Listing the Cloud Files Containers...")
conts = self.cf.get_all_containers()
if conts:
for cont in conts:
- print "%s - %s files, %s bytes" % (cont.name,
- cont.object_count, cont.total_bytes)
+ print("%s - %s files, %s bytes" % (cont.name,
+ cont.object_count, cont.total_bytes))
else:
- print "FAIL!"
+ print("FAIL!")
self.failures.append("CONTAINER LISTING")
- print
+ print()
def cf_make_container_public(self):
- print "Publishing the Cloud Files Container to CDN..."
+ print("Publishing the Cloud Files Container to CDN...")
self.smoke_cont.make_public()
uri = self.smoke_cont.cdn_uri
if uri:
- print "Success!"
+ print("Success!")
else:
- print "FAIL!"
+ print("FAIL!")
self.failures.append("PUBLISHING CDN")
- print
+ print()
def cf_make_container_private(self):
- print "Removing the Cloud Files Container from CDN..."
+ print("Removing the Cloud Files Container from CDN...")
try:
self.smoke_cont.make_private()
- print "Success!"
+ print("Success!")
except Exception as e:
- print "FAIL!"
+ print("FAIL!")
self.failures.append("UNPUBLISHING CDN")
- print
+ print()
def cf_upload_file(self):
- print "Uploading a Cloud Files object..."
+ print("Uploading a Cloud Files object...")
cont = self.smoke_cont
text = pyrax.utils.random_unicode(1024)
obj = cont.store_object("SMOKETEST_OBJECT", text)
@@ -342,23 +344,23 @@ def cf_upload_file(self):
self.cleanup_items.insert(0, obj)
all_objs = cont.get_object_names()
if obj.name in all_objs:
- print "Success!"
+ print("Success!")
else:
- print "FAIL!"
+ print("FAIL!")
self.failures.append("UPLOAD FILE")
- print
+ print()
def lb_list(self):
- print "Listing Load Balancers..."
+ print("Listing Load Balancers...")
lbs = self.clb.list()
if not lbs:
- print " - No load balancers to list!"
+ print(" - No load balancers to list!")
else:
for lb in lbs:
- print " -", lb.name
+ print(" -", lb.name)
def lb_create(self):
- print "Creating a Load Balancer..."
+ print("Creating a Load Balancer...")
node = self.clb.Node(address="10.177.1.1", port=80, condition="ENABLED")
vip = self.clb.VirtualIP(type="PUBLIC")
lb = self.clb.create("SMOKETEST_LB", port=80, protocol="HTTP",
@@ -367,40 +369,40 @@ def lb_create(self):
pyrax.utils.wait_until(lb, "status", ["ACTIVE", "ERROR"], interval=10,
verbose=True)
if lb:
- print "Success!"
+ print("Success!")
else:
- print "FAIL!"
+ print("FAIL!")
self.failures.append("LOAD_BALANCERS")
def dns_list(self):
- print "Listing DNS Domains..."
+ print("Listing DNS Domains...")
doms = self.dns.list()
if not doms:
- print " - No domains to list!"
+ print(" - No domains to list!")
else:
for dns in doms:
- print " -", dns.name
+ print(" -", dns.name)
def dns_create_domain(self):
- print "Creating a DNS Domain..."
+ print("Creating a DNS Domain...")
domain_name = "SMOKETEST.example.edu"
try:
dom = self.dns.create(name=domain_name,
emailAddress="sample@example.edu", ttl=900,
comment="SMOKETEST sample domain")
- print "Success!"
+ print("Success!")
self.cleanup_items.append(dom)
except exc.DomainCreationFailed:
- print "FAIL!"
+ print("FAIL!")
self.failures.append("DNS DOMAIN CREATION")
def dns_create_record(self):
- print "Creating a DNS Record..."
+ print("Creating a DNS Record...")
domain_name = "SMOKETEST.example.edu"
try:
dom = self.dns.find(name=domain_name)
except exc.NotFound:
- print "Smoketest domain not found; skipping record test."
+ print("Smoketest domain not found; skipping record test.")
self.failures.append("DNS RECORD CREATION")
return
a_rec = {"type": "A",
@@ -409,44 +411,44 @@ def dns_create_record(self):
"ttl": 6000}
try:
recs = dom.add_records(a_rec)
- print "Success!"
+ print("Success!")
# No need to cleanup, since domain deletion also deletes the recs.
# self.cleanup_items.extend(recs)
except exc.DomainRecordAdditionFailed:
- print "FAIL!"
+ print("FAIL!")
self.failures.append("DNS RECORD CREATION")
def cmn_list_check_types(self):
- print "Listing Monitoring Check Types..."
+ print("Listing Monitoring Check Types...")
cts = self.cmn.list_check_types()
for ct in cts:
- print " -", ct.id, ct.type
- print
+ print(" -", ct.id, ct.type)
+ print()
def cmn_list_monitoring_zones(self):
- print "Listing Monitoring Zones..."
+ print("Listing Monitoring Zones...")
zones = self.cmn.list_monitoring_zones()
for zone in zones:
- print " -", zone.id, zone.name
- print
+ print(" -", zone.id, zone.name)
+ print()
def cmn_create_entity(self):
- print "Creating a Monitoring Entity..."
+ print("Creating a Monitoring Entity...")
srv = self.smoke_server
ip = srv.networks["public"][0]
try:
self.smoke_entity = self.cmn.create_entity(name="SMOKETEST_entity",
ip_addresses={"main": ip})
self.cleanup_items.append(self.smoke_entity)
- print "Success!"
+ print("Success!")
except Exception:
- print "FAIL!"
+ print("FAIL!")
self.smoke_entity = None
self.failures.append("MONITORING CREATE ENTITY")
- print
+ print()
def cmn_create_check(self):
- print "Creating a Monitoring Check..."
+ print("Creating a Monitoring Check...")
ent = self.smoke_entity
alias = ent.ip_addresses.keys()[0]
try:
@@ -454,78 +456,78 @@ def cmn_create_check(self):
label="SMOKETEST_check", check_type="remote.ping",
details={"count": 5}, monitoring_zones_poll=["mzdfw"],
period=60, timeout=20, target_alias=alias)
- print "Success!"
+ print("Success!")
self.cleanup_items.append(self.smoke_check)
except Exception:
- print "FAIL!"
+ print("FAIL!")
self.smoke_check = None
self.failures.append("MONITORING CREATE CHECK")
- print
+ print()
def cmn_create_notification(self):
- print "Creating a Monitoring Notification..."
+ print("Creating a Monitoring Notification...")
email = "smoketest@example.com"
try:
self.smoke_notification = self.cmn.create_notification("email",
label="smoketest", details={"address": email})
- print "Success!"
+ print("Success!")
self.cleanup_items.append(self.smoke_notification)
except Exception:
- print "FAIL!"
+ print("FAIL!")
self.smoke_notification = None
self.failures.append("MONITORING CREATE NOTIFICATION")
- print
+ print()
def cmn_create_notification_plan(self):
if not self.smoke_notification:
- print ("No monitoring notification found; skipping notification "
+ print("No monitoring notification found; skipping notification "
"creation...")
return
- print "Creating a Monitoring Notification Plan..."
+ print("Creating a Monitoring Notification Plan...")
try:
self.smoke_notification_plan = self.cmn.create_notification_plan(
label="smoketest plan", ok_state=self.smoke_notification)
- print "Success!"
+ print("Success!")
self.cleanup_items.append(self.smoke_notification_plan)
except Exception as e:
- print "FAIL!", e
+ print("FAIL!", e)
self.smoke_notification_plan = None
self.failures.append("MONITORING CREATE NOTIFICATION PLAN")
- print
+ print()
def cmn_create_alarm(self):
if not self.smoke_notification_plan:
- print "No monitoring plan found; skipping alarm creation..."
+ print("No monitoring plan found; skipping alarm creation...")
return
- print "Creating a Monitoring Alarm..."
+ print("Creating a Monitoring Alarm...")
try:
self.smoke_alarm = self.cmn.create_alarm(self.smoke_entity,
self.smoke_check, self.smoke_notification_plan,
label="smoke alarm")
- print "Success!"
+ print("Success!")
self.cleanup_items.append(self.smoke_alarm)
except Exception:
- print "FAIL!"
+ print("FAIL!")
self.failures.append("MONITORING CREATE ALARM")
- print
+ print()
def cleanup(self):
- print "Cleaning up..."
+ print("Cleaning up...")
for item in self.cleanup_items:
try:
item.delete()
- print " - Deleting:",
+ print(" - Deleting:", end=' ')
try:
- print item.name
+ print(item.name)
except AttributeError:
- print item
+ print(item)
except exc.NotFound:
# Some items are deleted along with others (e.g., DNS records
# when a domain is deleted), so don't complain.
pass
except Exception as e:
- print "Could not delete '%s': %s" % (item, e)
+ print("Could not delete '%s': %s" % (item, e))
@@ -550,10 +552,10 @@ def cleanup(self):
start = time.time()
pyrax.keyring_auth()
for region in regions:
- print
- print "=" * 77
- print "Starting test for region: %s" % region
- print "=" * 77
+ print()
+ print("=" * 77)
+ print("Starting test for region: %s" % region)
+ print("=" * 77)
smoke_tester = SmokeTester(region)
try:
smoke_tester.run_tests()
@@ -561,15 +563,15 @@ def cleanup(self):
finally:
smoke_tester.cleanup()
- print
- print "=" * 88
+ print()
+ print("=" * 88)
if smoke_tester.failures:
- print "The following tests failed:"
+ print("The following tests failed:")
for failure in smoke_tester.failures:
- print " -", failure
+ print(" -", failure)
else:
- print "All tests passed!"
+ print("All tests passed!")
end = time.time()
- print
- print "Running the smoketests took %6.1f seconds." % (end - start)
- print
+ print()
+ print("Running the smoketests took %6.1f seconds." % (end - start))
+ print()
diff --git a/tests/unit/test_cf_client.py b/tests/unit/test_cf_client.py
index 0e7f9fff..a1abc805 100644
--- a/tests/unit/test_cf_client.py
+++ b/tests/unit/test_cf_client.py
@@ -7,6 +7,8 @@
import unittest
import uuid
+import six
+
from mock import ANY, call, patch
from mock import MagicMock as Mock
@@ -717,7 +719,7 @@ def test_upload_folder_with_files(self):
num_files = 10
fake_upload_key = "abcd"
with utils.SelfDeletingTempDirectory() as tmpdir:
- for idx in xrange(num_files):
+ for idx in six.moves.range(num_files):
nm = "file%s" % idx
pth = os.path.join(tmpdir, nm)
open(pth, "w").write("test")
@@ -752,7 +754,7 @@ def test_sync_folder_to_container(self):
cont = clt.create_container(cont_name)
num_files = 7
with utils.SelfDeletingTempDirectory() as tmpdir:
- for idx in xrange(num_files):
+ for idx in six.moves.range(num_files):
nm = "file%s" % idx
pth = os.path.join(tmpdir, nm)
open(pth, "w").write("test")
@@ -775,11 +777,11 @@ def test_sync_folder_to_container_hidden(self):
num_hid_files = 4
num_all_files = num_vis_files + num_hid_files
with utils.SelfDeletingTempDirectory() as tmpdir:
- for idx in xrange(num_vis_files):
+ for idx in six.moves.range(num_vis_files):
nm = "file%s" % idx
pth = os.path.join(tmpdir, nm)
open(pth, "w").write("test")
- for idx in xrange(num_hid_files):
+ for idx in six.moves.range(num_hid_files):
nm = ".file%s" % idx
pth = os.path.join(tmpdir, nm)
open(pth, "w").write("test")
@@ -802,13 +804,13 @@ def test_sync_folder_to_container_nested(self):
num_nested_files = 6
num_all_files = num_files + num_nested_files
with utils.SelfDeletingTempDirectory() as tmpdir:
- for idx in xrange(num_files):
+ for idx in six.moves.range(num_files):
nm = "file%s" % idx
pth = os.path.join(tmpdir, nm)
open(pth, "w").write("test")
nested_folder = os.path.join(tmpdir, "nested")
os.mkdir(nested_folder)
- for idx in xrange(num_nested_files):
+ for idx in six.moves.range(num_nested_files):
nm = "file%s" % idx
pth = os.path.join(nested_folder, nm)
open(pth, "w").write("test")
@@ -1234,8 +1236,10 @@ def test_handle_swiftclient_exception_container(self):
client = self.client
gc = client.get_container
client.get_container = Mock()
- client.get_container.side_effect = _swift_client.ClientException(
- "Container GET failed: https://example.com/some_container 404")
+ side_effect = _swift_client.ClientException("Container GET failed: "
+ "https://example.com/some_container 404")
+ side_effect.http_status = 404
+ client.get_container.side_effect = side_effect
# Note: we're using delete_object because its first call
# is get_container()
self.assertRaises(exc.NoSuchContainer, client.delete_object,
@@ -1247,9 +1251,9 @@ def test_handle_swiftclient_exception_object(self):
gc = client.get_container
client.get_container = Mock()
go = client.get_object
- client.get_object = Mock()
- client.get_object.side_effect = _swift_client.ClientException(
- "Object GET failed: https://example.com/cont/some_object 404")
+ bad = _swift_client.ClientException("Object GET failed: "
+ "https://example.com/cont/some_object 404", http_status=404)
+ client.get_object = Mock(side_effect=bad)
# Note: we're using copy_object because it calls get_object().
self.assertRaises(exc.NoSuchObject, client.copy_object,
"some_container", "some_object", "fake")
diff --git a/tests/unit/test_cf_container.py b/tests/unit/test_cf_container.py
index bd2a7885..98330bc9 100644
--- a/tests/unit/test_cf_container.py
+++ b/tests/unit/test_cf_container.py
@@ -162,6 +162,7 @@ def test_get_object_missing(self):
cont.client.connection.get_container = Mock()
side_effect = _swift_client.ClientException(
"Object GET failed: https://example.com/cont/some_object 404")
+ side_effect.http_status = 404
cont.client.connection.head_object = Mock(side_effect=side_effect)
self.assertRaises(exc.NoSuchObject, cont.get_object, "missing")
diff --git a/tests/unit/test_image.py b/tests/unit/test_image.py
new file mode 100644
index 00000000..40fd88ac
--- /dev/null
+++ b/tests/unit/test_image.py
@@ -0,0 +1,577 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+import os
+import random
+import unittest
+
+from mock import patch
+from mock import MagicMock as Mock
+
+import pyrax
+from pyrax.manager import BaseManager
+import pyrax.image
+from pyrax.image import assure_image
+from pyrax.image import ImageMember
+from pyrax.image import ImageTasksManager
+from pyrax.image import JSONSchemaManager
+
+import pyrax.exceptions as exc
+import pyrax.utils as utils
+
+from pyrax import fakes
+
+
+class ImageTest(unittest.TestCase):
+ def __init__(self, *args, **kwargs):
+ super(ImageTest, self).__init__(*args, **kwargs)
+
+ def setUp(self):
+ self.client = fakes.FakeImageClient()
+ self.client._manager = fakes.FakeImageManager(self.client)
+ self.image = fakes.FakeImage()
+ super(ImageTest, self).setUp()
+
+ def tearDown(self):
+ super(ImageTest, self).tearDown()
+
+ def test_assure_image(self):
+ class TestClient(object):
+ _manager = fakes.FakeManager()
+
+ @assure_image
+ def test_method(self, img):
+ return img
+
+ client = TestClient()
+ client._manager.get = Mock(return_value=self.image)
+ # Pass the image
+ ret = client.test_method(self.image)
+ self.assertTrue(ret is self.image)
+ # Pass the ID
+ ret = client.test_method(self.image.id)
+ self.assertTrue(ret is self.image)
+
+ def test_img_update(self):
+ img = self.image
+ key = utils.random_unicode()
+ val = utils.random_unicode()
+ img.manager.update = Mock()
+ img.update({key: val})
+ img.manager.update.assert_called_once_with(img, {key: val})
+
+ def test_img_change_name(self):
+ img = self.image
+ nm = utils.random_unicode()
+ img.update = Mock()
+ img.change_name(nm)
+ img.update.assert_called_once_with({"name": nm})
+
+ def test_img_list_members(self):
+ img = self.image
+ img._member_manager.list = Mock()
+ img.list_members()
+ img._member_manager.list.assert_called_once_with()
+
+ def test_img_get_member(self):
+ img = self.image
+ member = utils.random_unicode()
+ img._member_manager.get = Mock()
+ img.get_member(member)
+ img._member_manager.get.assert_called_once_with(member)
+
+ def test_img_create_member(self):
+ img = self.image
+ project_id = utils.random_unicode()
+ img._member_manager.create = Mock()
+ img.add_member(project_id)
+ img._member_manager.create.assert_called_once_with(name=None,
+ project_id=project_id)
+
+ def test_img_delete_member(self):
+ img = self.image
+ project_id = utils.random_unicode()
+ img._member_manager.delete = Mock()
+ img.delete_member(project_id)
+ img._member_manager.delete.assert_called_once_with(project_id)
+
+ def test_img_add_tag(self):
+ img = self.image
+ tag = utils.random_unicode()
+ img._tag_manager.add = Mock()
+ img.add_tag(tag)
+ img._tag_manager.add.assert_called_once_with(tag)
+
+ def test_img_delete_tag(self):
+ img = self.image
+ tag = utils.random_unicode()
+ img._tag_manager.delete = Mock()
+ img.delete_tag(tag)
+ img._tag_manager.delete.assert_called_once_with(tag)
+
+ def test_member_id(self):
+ mid = utils.random_unicode()
+ member = ImageMember(self.client._manager, {"member_id": mid})
+ self.assertEqual(member.id, mid)
+
+ def test_imgmgr_create_body(self):
+ clt = self.client
+ mgr = clt._manager
+ nm = utils.random_unicode()
+ meta = utils.random_unicode()
+ body = mgr._create_body(nm, metadata=meta)
+ self.assertEqual(body, {"metadata": meta})
+
+ def test_imgmgr_create_body_empty(self):
+ clt = self.client
+ mgr = clt._manager
+ nm = utils.random_unicode()
+ body = mgr._create_body(nm)
+ self.assertEqual(body, {})
+
+ def test_imgmgr_list(self):
+ clt = self.client
+ mgr = clt._manager
+ limit = utils.random_unicode()
+ marker = utils.random_unicode()
+ name = utils.random_unicode()
+ visibility = utils.random_unicode()
+ member_status = utils.random_unicode()
+ owner = utils.random_unicode()
+ tag = utils.random_unicode()
+ status = utils.random_unicode()
+ size_min = utils.random_unicode()
+ size_max = utils.random_unicode()
+ sort_key = utils.random_unicode()
+ sort_dir = utils.random_unicode()
+ return_raw = utils.random_unicode()
+ qs = utils.random_unicode()
+ mgr._list = Mock()
+ sav = utils.dict_to_qs
+ utils.dict_to_qs = Mock(return_value=qs)
+ expected = "/%s?%s" % (mgr.uri_base, qs)
+ mgr.list(limit=limit, marker=marker, name=name, visibility=visibility,
+ member_status=member_status, owner=owner, tag=tag,
+ status=status, size_min=size_min, size_max=size_max,
+ sort_key=sort_key, sort_dir=sort_dir, return_raw=return_raw)
+ mgr._list.assert_called_once_with(expected, return_raw=return_raw)
+ utils.dict_to_qs = sav
+
+ def test_imgmgr_list_all(self):
+ clt = self.client
+ mgr = clt._manager
+ next_link = "/images?marker=00000000-0000-0000-0000-0000000000"
+ fake_body = {"images": [{"name": "fake1"}], "next": "/v2%s" % next_link}
+ mgr.list = Mock(return_value=(None, fake_body))
+ fake_last_body = {"images": [{"name": "fake2"}], "next": ""}
+ mgr.api.method_get = Mock(return_value=(None, fake_last_body))
+ ret = mgr.list_all()
+ self.assertEqual(len(ret), 2)
+ mgr.list.assert_called_once_with(name=None, visibility=None,
+ member_status=None, owner=None, tag=None, status=None,
+ size_min=None, size_max=None, sort_key=None, sort_dir=None,
+ return_raw=True)
+ mgr.api.method_get.assert_called_once_with(next_link)
+
+ def test_imgmgr_update(self):
+ clt = self.client
+ mgr = clt._manager
+ img = self.image
+ setattr(img, "foo", "old")
+ valdict = {"foo": "new", "bar": "new"}
+ mgr.api.method_patch = Mock(return_value=(None, None))
+ mgr.get = Mock(return_value=img)
+ exp_uri = "/%s/%s" % (mgr.uri_base, img.id)
+ exp_body = [{"op": "replace", "path": "/foo", "value": "new"},
+ {"op": "add", "path": "/bar", "value": "new"}]
+ exp_hdrs = {"Content-Type":
+ "application/openstack-images-v2.1-json-patch"}
+ mgr.update(img, valdict)
+ mgr.api.method_patch.assert_called_once_with(exp_uri, body=exp_body,
+ headers=exp_hdrs)
+
+ def test_imgmgr_update_member(self):
+ clt = self.client
+ mgr = clt._manager
+ img = self.image
+ status = random.choice(("pending", "accepted", "rejected"))
+ sav = pyrax.identity.tenant_id
+ project_id = utils.random_unicode()
+ pyrax.identity.tenant_id = project_id
+ exp_uri = "/%s/%s/members/%s" % (mgr.uri_base, img.id, project_id)
+ exp_body = {"status": status}
+ mgr.api.method_put = Mock(return_value=(None, None))
+ mgr.update_image_member(img.id, status)
+ mgr.api.method_put.assert_called_once_with(exp_uri, body=exp_body)
+ pyrax.identity.tenant_id = sav
+
+ def test_imgmgr_update_member_bad(self):
+ clt = self.client
+ mgr = clt._manager
+ img = self.image
+ bad_status = "BAD"
+ self.assertRaises(exc.InvalidImageMemberStatus, mgr.update_image_member,
+ img.id, bad_status)
+
+ def test_imgmgr_update_member_not_found(self):
+ clt = self.client
+ mgr = clt._manager
+ img = self.image
+ status = random.choice(("pending", "accepted", "rejected"))
+ sav = pyrax.identity.tenant_id
+ project_id = utils.random_unicode()
+ pyrax.identity.tenant_id = project_id
+ exp_uri = "/%s/%s/members/%s" % (mgr.uri_base, img.id, project_id)
+ exp_body = {"status": status}
+ mgr.api.method_put = Mock(side_effect=exc.NotFound(""))
+ self.assertRaises(exc.InvalidImageMember, mgr.update_image_member,
+ img.id, status)
+ pyrax.identity.tenant_id = sav
+
+ def test_img_member_mgr_create_body(self):
+ img = self.image
+ mgr = img._member_manager
+ nm = utils.random_unicode()
+ project_id = utils.random_unicode()
+ ret = mgr._create_body(nm, project_id)
+ self.assertEqual(ret, {"member": project_id})
+
+ def test_img_member_mgr_create(self):
+ img = self.image
+ mgr = img._member_manager
+ nm = utils.random_unicode()
+ val = utils.random_unicode()
+ sav = BaseManager.create
+ BaseManager.create = Mock(return_value=val)
+ ret = mgr.create(nm)
+ self.assertEqual(ret, val)
+ BaseManager.create = sav
+
+ def test_img_member_mgr_create_403(self):
+ img = self.image
+ mgr = img._member_manager
+ nm = utils.random_unicode()
+ sav = BaseManager.create
+ err = exc.Forbidden(403)
+ BaseManager.create = Mock(side_effect=err)
+ self.assertRaises(exc.UnsharableImage, mgr.create, nm)
+ BaseManager.create = sav
+
+ def test_img_member_mgr_create_other(self):
+ img = self.image
+ mgr = img._member_manager
+ nm = utils.random_unicode()
+ sav = BaseManager.create
+ err = exc.OverLimit(413)
+ BaseManager.create = Mock(side_effect=err)
+ self.assertRaises(exc.OverLimit, mgr.create, nm)
+ BaseManager.create = sav
+
+ def test_img_tag_mgr_create(self):
+ img = self.image
+ mgr = img._tag_manager
+ nm = utils.random_unicode()
+ ret = mgr._create_body(nm)
+ self.assertEqual(ret, {})
+
+ def test_img_tag_mgr_add(self):
+ img = self.image
+ mgr = img._tag_manager
+ tag = utils.random_unicode()
+ exp_uri = "/%s/%s" % (mgr.uri_base, tag)
+ mgr.api.method_put = Mock(return_value=(None, None))
+ mgr.add(tag)
+ mgr.api.method_put.assert_called_once_with(exp_uri)
+
+ def test_img_tasks_mgr_create_export(self):
+ clt = self.client
+ mgr = clt._tasks_manager
+ img = self.image
+ cont = utils.random_unicode()
+ img_format = utils.random_unicode()
+ img_name = utils.random_unicode()
+ name = "export"
+ ret = mgr._create_body(name, img=img, cont=cont, img_format=img_format,
+ img_name=img_name)
+ exp = {"type": name, "input": {
+ "image_uuid": img.id,
+ "receiving_swift_container": cont}}
+ self.assertEqual(ret, exp)
+
+ def test_img_tasks_mgr_create_import(self):
+ clt = self.client
+ mgr = clt._tasks_manager
+ img = self.image
+ cont = utils.random_unicode()
+ img_format = utils.random_unicode()
+ img_name = utils.random_unicode()
+ name = "import"
+ ret = mgr._create_body(name, img=img, cont=cont, img_format=img_format,
+ img_name=img_name)
+ exp = {"type": name, "input": {
+ "image_properties": {"name": img_name},
+ "import_from": "%s/%s" % (cont, img.id),
+ "import_from_format": img_format}}
+ self.assertEqual(ret, exp)
+
+ def test_img_tasks_mgr_create(self):
+ clt = self.client
+ mgr = clt._tasks_manager
+ nm = utils.random_unicode()
+ cont = utils.random_unicode()
+ sav = pyrax.cloudfiles
+ sav_create = BaseManager.create
+ BaseManager.create = Mock()
+
+ class FakeCF(object):
+ def get_container(self, cont):
+ return cont
+
+ pyrax.cloudfiles = FakeCF()
+ mgr.create(nm, cont=cont)
+ BaseManager.create.assert_called_once_with(nm, cont=cont)
+ pyrax.cloudfiles = sav
+ BaseManager.create = sav_create
+
+ def test_jsonscheme_mgr(self):
+ mgr = JSONSchemaManager(self.client)
+ nm = utils.random_unicode()
+ ret = mgr._create_body(nm)
+ self.assertIsNone(ret)
+
+ def test_jsonscheme_mgr_images(self):
+ mgr = JSONSchemaManager(self.client)
+ mgr.api.method_get = Mock(return_value=(None, None))
+ exp_uri = "/%s/images" % mgr.uri_base
+ mgr.images()
+ mgr.api.method_get.assert_called_once_with(exp_uri)
+
+ def test_jsonscheme_mgr_image(self):
+ mgr = JSONSchemaManager(self.client)
+ mgr.api.method_get = Mock(return_value=(None, None))
+ exp_uri = "/%s/image" % mgr.uri_base
+ mgr.image()
+ mgr.api.method_get.assert_called_once_with(exp_uri)
+
+ def test_jsonscheme_mgr_members(self):
+ mgr = JSONSchemaManager(self.client)
+ mgr.api.method_get = Mock(return_value=(None, None))
+ exp_uri = "/%s/members" % mgr.uri_base
+ mgr.image_members()
+ mgr.api.method_get.assert_called_once_with(exp_uri)
+
+ def test_jsonscheme_mgr_member(self):
+ mgr = JSONSchemaManager(self.client)
+ mgr.api.method_get = Mock(return_value=(None, None))
+ exp_uri = "/%s/member" % mgr.uri_base
+ mgr.image_member()
+ mgr.api.method_get.assert_called_once_with(exp_uri)
+
+ def test_jsonscheme_mgr_tasks(self):
+ mgr = JSONSchemaManager(self.client)
+ mgr.api.method_get = Mock(return_value=(None, None))
+ exp_uri = "/%s/tasks" % mgr.uri_base
+ mgr.image_tasks()
+ mgr.api.method_get.assert_called_once_with(exp_uri)
+
+ def test_jsonscheme_mgr_task(self):
+ mgr = JSONSchemaManager(self.client)
+ mgr.api.method_get = Mock(return_value=(None, None))
+ exp_uri = "/%s/task" % mgr.uri_base
+ mgr.image_task()
+ mgr.api.method_get.assert_called_once_with(exp_uri)
+
+ def test_clt_list(self):
+ clt = self.client
+ mgr = clt._manager
+ limit = utils.random_unicode()
+ marker = utils.random_unicode()
+ name = utils.random_unicode()
+ visibility = utils.random_unicode()
+ member_status = utils.random_unicode()
+ owner = utils.random_unicode()
+ tag = utils.random_unicode()
+ status = utils.random_unicode()
+ size_min = utils.random_unicode()
+ size_max = utils.random_unicode()
+ sort_key = utils.random_unicode()
+ sort_dir = utils.random_unicode()
+ mgr.list = Mock()
+ clt.list(limit=limit, marker=marker, name=name, visibility=visibility,
+ member_status=member_status, owner=owner, tag=tag,
+ status=status, size_min=size_min, size_max=size_max,
+ sort_key=sort_key, sort_dir=sort_dir)
+ mgr.list.assert_called_once_with(limit=limit, marker=marker, name=name,
+ visibility=visibility, member_status=member_status,
+ owner=owner, tag=tag, status=status, size_min=size_min,
+ size_max=size_max, sort_key=sort_key, sort_dir=sort_dir)
+
+ def test_clt_list_all(self):
+ clt = self.client
+ mgr = clt._manager
+ mgr.list_all = Mock()
+ clt.list_all()
+ mgr.list_all.assert_called_once_with(name=None, visibility=None,
+ member_status=None, owner=None, tag=None, status=None,
+ size_min=None, size_max=None, sort_key=None, sort_dir=None)
+
+ def test_clt_update(self):
+ clt = self.client
+ mgr = clt._manager
+ img = self.image
+ key = utils.random_unicode()
+ val = utils.random_unicode()
+ upd = {key: val}
+ mgr.update = Mock()
+ clt.update(img, upd)
+ mgr.update.assert_called_once_with(img, upd)
+
+ def test_clt_change_image_name(self):
+ clt = self.client
+ mgr = clt._manager
+ img = self.image
+ nm = utils.random_unicode()
+ clt.update = Mock()
+ clt.change_image_name(img, nm)
+ clt.update.assert_called_once_with(img, {"name": nm})
+
+ def test_clt_list_image_members(self):
+ clt = self.client
+ img = self.image
+ img.list_members = Mock()
+ clt.list_image_members(img)
+ img.list_members.assert_called_once_with()
+
+ def test_clt_get_image_member(self):
+ clt = self.client
+ img = self.image
+ member = utils.random_unicode()
+ img.get_member = Mock()
+ clt.get_image_member(img, member)
+ img.get_member.assert_called_once_with(member)
+
+ def test_clt_add_image_member(self):
+ clt = self.client
+ img = self.image
+ project_id = utils.random_unicode()
+ img.add_member = Mock()
+ clt.add_image_member(img, project_id)
+ img.add_member.assert_called_once_with(project_id)
+
+ def test_clt_delete_image_member(self):
+ clt = self.client
+ img = self.image
+ project_id = utils.random_unicode()
+ img.delete_member = Mock()
+ clt.delete_image_member(img, project_id)
+ img.delete_member.assert_called_once_with(project_id)
+
+ def test_clt_update_img_member(self):
+ clt = self.client
+ mgr = clt._manager
+ img = self.image
+ status = utils.random_unicode()
+ mgr.update_image_member = Mock()
+ clt.update_image_member(img, status)
+ mgr.update_image_member.assert_called_once_with(img, status)
+
+ def test_clt_add_image_tag(self):
+ clt = self.client
+ img = self.image
+ tag = utils.random_unicode()
+ img.add_tag = Mock()
+ clt.add_image_tag(img, tag)
+ img.add_tag.assert_called_once_with(tag)
+
+ def test_clt_delete_image_tag(self):
+ clt = self.client
+ img = self.image
+ tag = utils.random_unicode()
+ img.delete_tag = Mock()
+ clt.delete_image_tag(img, tag)
+ img.delete_tag.assert_called_once_with(tag)
+
+ def test_clt_list_tasks(self):
+ clt = self.client
+ mgr = clt._tasks_manager
+ mgr.list = Mock()
+ clt.list_tasks()
+ mgr.list.assert_called_once_with()
+
+ def test_clt_get_task(self):
+ clt = self.client
+ mgr = clt._tasks_manager
+ task = utils.random_unicode()
+ mgr.get = Mock()
+ clt.get_task(task)
+ mgr.get.assert_called_once_with(task)
+
+ def test_clt_export_task(self):
+ clt = self.client
+ mgr = clt._tasks_manager
+ img = self.image
+ cont = utils.random_unicode()
+ mgr.create = Mock()
+ clt.export_task(img, cont)
+ mgr.create.assert_called_once_with("export", img=img, cont=cont)
+
+ def test_clt_import_task(self):
+ clt = self.client
+ mgr = clt._tasks_manager
+ img = self.image
+ cont = utils.random_unicode()
+ img_format = utils.random_unicode()
+ img_name = utils.random_unicode()
+ mgr.create = Mock()
+ clt.import_task(img, cont, img_format=img_format, img_name=img_name)
+ mgr.create.assert_called_once_with("import", img=img, cont=cont,
+ img_format=img_format, img_name=img_name)
+
+ def test_clt_get_images_schema(self):
+ clt = self.client
+ mgr = clt._schema_manager
+ mgr.images = Mock()
+ clt.get_images_schema()
+ mgr.images.assert_called_once_with()
+
+ def test_clt_get_image_schema(self):
+ clt = self.client
+ mgr = clt._schema_manager
+ mgr.image = Mock()
+ clt.get_image_schema()
+ mgr.image.assert_called_once_with()
+
+ def test_clt_get_image_members_schema(self):
+ clt = self.client
+ mgr = clt._schema_manager
+ mgr.image_members = Mock()
+ clt.get_image_members_schema()
+ mgr.image_members.assert_called_once_with()
+
+ def test_clt_get_image_member_schema(self):
+ clt = self.client
+ mgr = clt._schema_manager
+ mgr.image_member = Mock()
+ clt.get_image_member_schema()
+ mgr.image_member.assert_called_once_with()
+
+ def test_clt_get_image_tasks_schema(self):
+ clt = self.client
+ mgr = clt._schema_manager
+ mgr.image_tasks = Mock()
+ clt.get_image_tasks_schema()
+ mgr.image_tasks.assert_called_once_with()
+
+ def test_clt_get_image_task_schema(self):
+ clt = self.client
+ mgr = clt._schema_manager
+ mgr.image_task = Mock()
+ clt.get_image_task_schema()
+ mgr.image_task.assert_called_once_with()
+
+
+
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/tests/unit/test_service_catalog.py b/tests/unit/test_service_catalog.py
index 95efbf49..ef7ace77 100644
--- a/tests/unit/test_service_catalog.py
+++ b/tests/unit/test_service_catalog.py
@@ -5,6 +5,8 @@
from mock import MagicMock as Mock
+import six
+
import pyrax.utils as utils
import pyrax.exceptions as exc
from pyrax import service_catalog
@@ -50,7 +52,7 @@ def test_url_for_object_store(self):
sc = self.service_catalog
ret = sc.url_for(service_type="object-store", attr="region",
filter_value="DFW")
- self.assertTrue(isinstance(ret, basestring))
+ self.assertTrue(isinstance(ret, six.string_types))
self.assertTrue("http" in ret)
diff --git a/tests/unit/test_utils.py b/tests/unit/test_utils.py
index 3b7d31d4..1f37e5d5 100644
--- a/tests/unit/test_utils.py
+++ b/tests/unit/test_utils.py
@@ -10,6 +10,8 @@
import time
import unittest
+import six
+
from mock import patch
from mock import MagicMock as Mock
@@ -38,7 +40,7 @@ def test_runproc(self):
def test_self_deleting_temp_file(self):
with utils.SelfDeletingTempfile() as tmp:
- self.assert_(isinstance(tmp, basestring))
+ self.assert_(isinstance(tmp, six.string_types))
self.assert_(os.path.exists(tmp))
self.assert_(os.path.isfile(tmp))
# File shoud be deleted after exiting the block
@@ -46,7 +48,7 @@ def test_self_deleting_temp_file(self):
def test_self_deleting_temp_directory(self):
with utils.SelfDeletingTempDirectory() as tmp:
- self.assert_(isinstance(tmp, basestring))
+ self.assert_(isinstance(tmp, six.string_types))
self.assert_(os.path.exists(tmp))
self.assert_(os.path.isdir(tmp))
# Directory shoud be deleted after exiting the block
@@ -111,7 +113,7 @@ def test_folder_size_bad_folder(self):
def test_folder_size_no_ignore(self):
with utils.SelfDeletingTempDirectory() as tmpdir:
# write 5 files of 100 bytes each
- for idx in xrange(5):
+ for idx in six.moves.range(5):
pth = os.path.join(tmpdir, "test%s" % idx)
with open(pth, "w") as ff:
ff.write(FAKE_CONTENT)
@@ -121,7 +123,7 @@ def test_folder_size_no_ignore(self):
def test_folder_size_ignore_string(self):
with utils.SelfDeletingTempDirectory() as tmpdir:
# write 5 files of 100 bytes each
- for idx in xrange(5):
+ for idx in six.moves.range(5):
pth = os.path.join(tmpdir, "test%s" % idx)
with open(pth, "w") as ff:
ff.write(FAKE_CONTENT)
@@ -132,7 +134,7 @@ def test_folder_size_ignore_string(self):
def test_folder_size_ignore_list(self):
with utils.SelfDeletingTempDirectory() as tmpdir:
# write 5 files of 100 bytes each
- for idx in xrange(5):
+ for idx in six.moves.range(5):
pth = os.path.join(tmpdir, "test%s" % idx)
with open(pth, "w") as ff:
ff.write(FAKE_CONTENT)