knife-cloudstack 0.0.13 → 0.0.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. data/CHANGES.rdoc +50 -0
  2. data/README.rdoc +221 -42
  3. data/lib/chef/knife/cs_account_list.rb +130 -0
  4. data/lib/chef/knife/cs_base.rb +98 -0
  5. data/lib/chef/knife/cs_baselist.rb +81 -0
  6. data/lib/chef/knife/cs_cluster_list.rb +93 -0
  7. data/lib/chef/knife/cs_config_list.rb +85 -0
  8. data/lib/chef/knife/cs_disk_list.rb +89 -0
  9. data/lib/chef/knife/cs_domain_list.rb +83 -0
  10. data/lib/chef/knife/cs_firewallrule_list.rb +95 -0
  11. data/lib/chef/knife/cs_host_list.rb +95 -0
  12. data/lib/chef/knife/cs_hosts.rb +2 -2
  13. data/lib/chef/knife/cs_iso_list.rb +103 -0
  14. data/lib/chef/knife/cs_network_list.rb +56 -46
  15. data/lib/chef/knife/cs_oscategory_list.rb +78 -0
  16. data/lib/chef/knife/cs_ostype_list.rb +80 -0
  17. data/lib/chef/knife/cs_pod_list.rb +93 -0
  18. data/lib/chef/knife/cs_project_list.rb +92 -0
  19. data/lib/chef/knife/cs_router_list.rb +94 -0
  20. data/lib/chef/knife/cs_server_create.rb +185 -144
  21. data/lib/chef/knife/cs_server_delete.rb +62 -79
  22. data/lib/chef/knife/cs_server_list.rb +136 -57
  23. data/lib/chef/knife/cs_server_reboot.rb +50 -54
  24. data/lib/chef/knife/cs_server_start.rb +48 -52
  25. data/lib/chef/knife/cs_server_stop.rb +54 -55
  26. data/lib/chef/knife/cs_service_list.rb +62 -41
  27. data/lib/chef/knife/cs_stack_create.rb +2 -2
  28. data/lib/chef/knife/cs_stack_delete.rb +2 -2
  29. data/lib/chef/knife/cs_template_create.rb +121 -0
  30. data/lib/chef/knife/cs_template_extract.rb +104 -0
  31. data/lib/chef/knife/cs_template_list.rb +65 -63
  32. data/lib/chef/knife/cs_template_register.rb +180 -0
  33. data/lib/chef/knife/cs_user_list.rb +93 -0
  34. data/lib/chef/knife/cs_volume_list.rb +94 -0
  35. data/lib/chef/knife/cs_zone_list.rb +55 -36
  36. data/lib/knife-cloudstack/connection.rb +75 -22
  37. data/lib/knife-cloudstack/string_to_regexp.rb +32 -0
  38. metadata +93 -61
@@ -16,8 +16,6 @@
16
16
  # limitations under the License.
17
17
  #
18
18
 
19
- require 'chef/knife'
20
-
21
19
  module KnifeCloudstack
22
20
  class CsStackDelete < Chef::Knife
23
21
 
@@ -25,6 +23,8 @@ module KnifeCloudstack
25
23
  require 'chef/json_compat'
26
24
  require 'chef/mash'
27
25
  require 'knife-cloudstack/connection'
26
+ require 'chef/knife'
27
+ Chef::Knife.load_deps
28
28
  KnifeCloudstack::CsServerDelete.load_deps
29
29
  end
30
30
 
@@ -0,0 +1,121 @@
1
+ #
2
+ # Author:: Sander Botman (<sbotman@schubergphilis.com>)
3
+ # Author:: Frank Breedijk (<fbreedijk@schubergphilis.com>)
4
+ # Copyright:: Copyright (c) 2013
5
+ # License:: Apache License, Version 2.0
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+ #
19
+
20
+ require 'chef/knife/cs_base'
21
+
22
+ module KnifeCloudstack
23
+ class CsTemplateCreate < Chef::Knife
24
+
25
+ include Chef::Knife::KnifeCloudstackBase
26
+
27
+ deps do
28
+ require 'knife-cloudstack/connection'
29
+ Chef::Knife.load_deps
30
+ end
31
+
32
+ banner "knife cs template create NAME (options)"
33
+
34
+ option :displaytext,
35
+ :short => "-T 'DISPLAY TEXT' ",
36
+ :long => "--displaytext 'DISPLAY TEXT'",
37
+ :description => "The display text of the template",
38
+ :required => true,
39
+ :on => :head
40
+
41
+ option :name,
42
+ :long => "--name NAME",
43
+ :description => "Specify templatename (without format checking)"
44
+
45
+ option :ostypeid,
46
+ :long => "--ostypeid ID",
47
+ :description => "Specify OS type ID",
48
+ :required => true,
49
+ :on => :head
50
+
51
+ option :volumeid,
52
+ :long => "--volumeid=ID",
53
+ :description => "Specify volume ID",
54
+ :required => true,
55
+ :on => :head
56
+
57
+ option :ispublic,
58
+ :long => "--[no-]public",
59
+ :description => "Make the template public after creation",
60
+ :boolean => true,
61
+ :default => false
62
+
63
+ option :isfeatured,
64
+ :long => "--[no-]featured",
65
+ :description => "Make the template featured after creation",
66
+ :boolean => true,
67
+ :default => false
68
+
69
+ option :passwordenabled,
70
+ :long => "--[no-]passwordenabled",
71
+ :description => "Make the template password reset enabled after creation",
72
+ :boolean => true,
73
+ :default => true
74
+
75
+ option :extractable,
76
+ :logn => "--[no-]extractable",
77
+ :description => "Make the template extractable after creation",
78
+ :boolean => "true",
79
+ :default => false
80
+
81
+ def run
82
+ validate_base_options
83
+
84
+ Chef::Log.debug("Validate hostname and options")
85
+ if locate_config_value(:name)
86
+ templatename = locate_config_value(:name)
87
+ else
88
+ templatename = @name_args.first
89
+ unless /^[a-zA-Z0-9][a-zA-Z0-9_\-#]*$/.match templatename then
90
+ ui.error "Invalid templatename. Please specify a simple name without any spaces"
91
+ exit 1
92
+ end
93
+ end
94
+
95
+ print "#{ui.color("Creating template: #{templatename}", :magenta)}\n"
96
+
97
+ params = {
98
+ 'command' => 'createTemplate',
99
+ 'name' => templatename,
100
+ 'displaytext' => locate_config_value(:displaytext),
101
+ 'ostypeid' => locate_config_value(:ostypeid),
102
+ 'volumeid' => locate_config_value(:volumeid),
103
+ }
104
+ params['ispublic'] = locate_config_value(:ispublic) if locate_config_value(:ispublic)
105
+ params['isfeatured'] = locate_config_value(:isfeatured) if locate_config_value(:isfeatured)
106
+ params['passwordenabled'] = locate_config_value(:passwordenabled) if locate_config_value(:passwordenabled)
107
+ params['extractable'] = locate_config_value(:extractable) if locate_config_value(:extractable)
108
+ json = connection.send_request(params)
109
+
110
+ if ! json then
111
+ ui.error("Unable to create template")
112
+ exit 1
113
+ end
114
+
115
+ print "Template #{json['id']} is being created in the background\n";
116
+
117
+ return json['id']
118
+ end
119
+
120
+ end # class
121
+ end
@@ -0,0 +1,104 @@
1
+ #
2
+ # Author:: Frank Breedijk (<fbreedijk@schubergphilis.com>)
3
+ # Author:: Sander Botman (<sbotman@schubergphilis.com>)
4
+ # Copyright:: Copyright (c) 2013
5
+ # License:: Apache License, Version 2.0
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+ #
19
+
20
+ require 'chef/knife/cs_base'
21
+
22
+ module KnifeCloudstack
23
+ class CsTemplateExtract < Chef::Knife
24
+
25
+ include Chef::Knife::KnifeCloudstackBase
26
+
27
+ deps do
28
+ require 'knife-cloudstack/connection'
29
+ Chef::Knife.load_deps
30
+ end
31
+
32
+ banner "knife cs template extract NAME (options)"
33
+
34
+ option :name,
35
+ :long => "--name NAME",
36
+ :description => "Name of template to extract (without format checking)"
37
+
38
+ option :zone,
39
+ :long => "--zone NAME",
40
+ :description => "Name of the zone to extract the template in"
41
+
42
+ def run
43
+ validate_base_options
44
+
45
+ Chef::Log.debug("Validate template name")
46
+ if locate_config_value(:name)
47
+ templatename = locate_config_value(:name)
48
+ else
49
+ templatename = @name_args.first
50
+ unless /^[a-zA-Z0-9][a-zA-Z0-9_\-# ]*$/.match templatename then
51
+ ui.error "Invalid templatename."
52
+ exit 1
53
+ end
54
+ end
55
+
56
+ zonename = locate_config_value(:zone)
57
+ if ! zonename
58
+ then
59
+ ui.error "No zone specified"
60
+ exit 1
61
+ end
62
+
63
+ print "#{ui.color("Extracting template: #{templatename}", :magenta)}\n"
64
+
65
+ Chef::Log.debug("Getting zone")
66
+
67
+ zone = connection.get_zone(
68
+ zonename,
69
+ )
70
+ if ! zone then
71
+ ui.error "Zone #{zonename} not found"
72
+ exit 1
73
+ end
74
+
75
+ Chef::Log.debug("Getting template")
76
+
77
+ template = connection.get_template(
78
+ templatename,
79
+ )
80
+ if ! template then
81
+ ui.error "Template #{templatename} not found"
82
+ exit 1
83
+ end
84
+
85
+ Chef::Log.debug("Extracting template")
86
+ params = {
87
+ 'command' => 'extractTemplate',
88
+ 'id' => template["id"],
89
+ 'mode' => "HTTP_DOWNLOAD",
90
+ 'zoneid' => zone["id"]
91
+ }
92
+ json = connection.send_async_request(params)
93
+
94
+ if json then
95
+ url = json["template"]["url"]
96
+ print "\n#{url}\n"
97
+ else
98
+ ui.error "Template extraction failed.\n"
99
+ exit 1
100
+ end
101
+ end
102
+
103
+ end # class
104
+ end
@@ -1,6 +1,8 @@
1
1
  #
2
2
  # Author:: Ryan Holmes (<rholmes@edmunds.com>)
3
+ # Author:: Sander Botman (<sbotman@schubergphilis.com>)
3
4
  # Copyright:: Copyright (c) 2011 Edmunds, Inc.
5
+ # Copyright:: Copyright (c) 2013 Sander Botman.
4
6
  # License:: Apache License, Version 2.0
5
7
  #
6
8
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -16,85 +18,90 @@
16
18
  # limitations under the License.
17
19
  #
18
20
 
19
- require 'chef/knife'
21
+ require 'chef/knife/cs_base'
22
+ require 'chef/knife/cs_baselist'
20
23
 
21
24
  module KnifeCloudstack
22
25
  class CsTemplateList < Chef::Knife
23
26
 
24
- MEGABYTES = 1024 * 1024
27
+ include Chef::Knife::KnifeCloudstackBase
28
+ include Chef::Knife::KnifeCloudstackBaseList
25
29
 
26
30
  deps do
27
31
  require 'knife-cloudstack/connection'
32
+ require 'chef/knife'
33
+ Chef::Knife.load_deps
28
34
  end
29
35
 
30
36
  banner "knife cs template list (options)"
31
37
 
32
- option :filter,
33
- :short => "-L FILTER",
34
- :long => "--filter FILTER",
35
- :description => "The template search filter. Default is 'featured'",
36
- :default => "featured"
38
+ option :listall,
39
+ :long => "--listall",
40
+ :description => "List all templates",
41
+ :boolean => true
42
+
43
+ option :index,
44
+ :long => "--index",
45
+ :description => "Add index numbers to the output",
46
+ :boolean => true
37
47
 
38
- option :cloudstack_url,
39
- :short => "-U URL",
40
- :long => "--cloudstack-url URL",
41
- :description => "The CloudStack endpoint URL",
42
- :proc => Proc.new { |url| Chef::Config[:knife][:cloudstack_url] = url }
43
-
44
- option :cloudstack_api_key,
45
- :short => "-A KEY",
46
- :long => "--cloudstack-api-key KEY",
47
- :description => "Your CloudStack API key",
48
- :proc => Proc.new { |key| Chef::Config[:knife][:cloudstack_api_key] = key }
49
-
50
- option :cloudstack_secret_key,
51
- :short => "-K SECRET",
52
- :long => "--cloudstack-secret-key SECRET",
53
- :description => "Your CloudStack secret key",
54
- :proc => Proc.new { |key| Chef::Config[:knife][:cloudstack_secret_key] = key }
55
-
56
- option :cloudstack_project,
57
- :short => "-P PROJECT_NAME",
58
- :long => '--cloudstack-project PROJECT_NAME',
59
- :description => "Cloudstack Project in which to create server",
60
- :proc => Proc.new { |v| Chef::Config[:knife][:cloudstack_project] = v },
61
- :default => nil
62
-
63
- option :use_http_ssl,
64
- :long => '--[no-]use-http-ssl',
65
- :description => 'Support HTTPS',
66
- :boolean => true,
67
- :default => true
48
+ option :templatefilter,
49
+ :long => "--templatefilter FILTER",
50
+ :description => "Default: 'featured'. Options: 'self','self-executable','executable','community'",
51
+ :default => "featured"
68
52
 
69
53
  def run
54
+ validate_base_options
70
55
 
71
- connection = CloudstackClient::Connection.new(
72
- locate_config_value(:cloudstack_url),
73
- locate_config_value(:cloudstack_api_key),
74
- locate_config_value(:cloudstack_secret_key),
75
- locate_config_value(:cloudstack_project),
76
- locate_config_value(:use_http_ssl)
77
- )
56
+ object_list = []
57
+ object_list << ui.color('Index', :bold) if locate_config_value(:index)
78
58
 
79
- template_list = [
59
+ if locate_config_value(:fields)
60
+ locate_config_value(:fields).split(',').each { |n| object_list << ui.color(("#{n}").strip, :bold) }
61
+ else
62
+ [
80
63
  ui.color('Name', :bold),
81
64
  ui.color('Size', :bold),
82
65
  ui.color('Zone', :bold),
83
66
  ui.color('Public', :bold),
84
- ui.color('Created', :bold),
85
- ]
86
-
87
- filter = config['filter']
88
- templates = connection.list_templates(filter)
89
- templates.each do |t|
90
- template_list << t['name']
91
- #template_list << (human_file_size(t['size']) || 'Unknown')
92
- template_list << t['zonename']
93
- template_list << t['ispublic'].to_s
94
- template_list << t['created']
67
+ ui.color('Created', :bold)
68
+ ].each { |field| object_list << field }
95
69
  end
96
- puts ui.list(template_list, :columns_across, 5)
97
70
 
71
+ columns = object_list.count
72
+ object_list = [] if locate_config_value(:noheader)
73
+
74
+ connection_result = connection.list_object(
75
+ "listTemplates",
76
+ "template",
77
+ locate_config_value(:filter),
78
+ locate_config_value(:listall),
79
+ nil,
80
+ nil,
81
+ locate_config_value(:templatefilter)
82
+ )
83
+
84
+ output_format(connection_result)
85
+
86
+ index_num = 0
87
+ connection_result.each do |r|
88
+ if locate_config_value(:index)
89
+ index_num += 1
90
+ object_list << index_num.to_s
91
+ end
92
+
93
+ if locate_config_value(:fields)
94
+ locate_config_value(:fields).downcase.split(',').each { |n| object_list << ((r[("#{n}").strip]).to_s || 'N/A') }
95
+ else
96
+ object_list << r['name'].to_s
97
+ object_list << (r['size'] ? human_file_size(r['size']) : 'Unknown')
98
+ object_list << r['zonename'].to_s
99
+ object_list << r['ispublic'].to_s
100
+ object_list << r['created']
101
+ end
102
+ end
103
+ puts ui.list(object_list, :uneven_columns_across, columns)
104
+ list_object_fields(connection_result) if locate_config_value(:fieldlist)
98
105
  end
99
106
 
100
107
  def human_file_size n
@@ -103,12 +110,7 @@ module KnifeCloudstack
103
110
  n /= 1024.0
104
111
  count += 1
105
112
  end
106
- format("%.2f", n) + %w(B KB MB GB TB)[count]
107
- end
108
-
109
- def locate_config_value(key)
110
- key = key.to_sym
111
- Chef::Config[:knife][key] || config[key]
113
+ format("%.0f", n) + %w(B KB MB GB TB)[count]
112
114
  end
113
115
 
114
116
  end
@@ -0,0 +1,180 @@
1
+ #
2
+ # Author:: Frank Breedijk (<fbreedijk@schubergphilis.com>)
3
+ # Author:: Sander Botman (<sbotman@schubergphilis.com>)
4
+ # Copyright:: Copyright (c) 2013
5
+ # License:: Apache License, Version 2.0
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+ #
19
+
20
+ require 'chef/knife/cs_base'
21
+
22
+ module KnifeCloudstack
23
+ class CsTemplateRegister < Chef::Knife
24
+
25
+ include Chef::Knife::KnifeCloudstackBase
26
+
27
+ deps do
28
+ require 'knife-cloudstack/connection'
29
+ Chef::Knife.load_deps
30
+ end
31
+
32
+ banner "knife cs template register NAME (options)"
33
+
34
+ option :name,
35
+ :long => "--name NAME",
36
+ :description => "Name of template to register (without format checking)"
37
+
38
+ option :displaytext,
39
+ :long => "--displaytext DESCRIPTION",
40
+ :description => "Description of the template as shown in CloudStack"
41
+
42
+ option :format,
43
+ :long => "--format FORMAT",
44
+ :description => "Format of the template file QCOW2, RAW or VHD (default)",
45
+ :default => "VHD"
46
+
47
+ option :hypervisor,
48
+ :long => "--hypervisor NAME",
49
+ :description => "Target hypervisor for the template (default XEN)",
50
+ :default => "XenServer"
51
+
52
+ option :ostypeid,
53
+ :long => '--ostypeid OSTYPEID',
54
+ :description => "The ID of the OS Type that best represents the OS of this template"
55
+
56
+ option :url,
57
+ :long => '--url URL',
58
+ :description => "The URL of where the template is hosted. Including http:// and https://"
59
+
60
+ option :zone,
61
+ :long => "--zone NAME",
62
+ :description => "Name of the zone to register the template in. Default: All zones",
63
+ :default => -1
64
+
65
+ option :bits,
66
+ :long => "--bits 32|64",
67
+ :description => "32 or 64 bits support, defaults to 64",
68
+ :default => 64
69
+
70
+ option :extractable,
71
+ :long => "--[no-]extractable",
72
+ :description => "Is the template extracable. Default: NO",
73
+ :boolean => true,
74
+ :default => false
75
+
76
+ option :featured,
77
+ :long => "--[no-]featured",
78
+ :description => "Is the tempalte featured? Default: NO",
79
+ :boolean => true,
80
+ :default => false
81
+
82
+ option :public,
83
+ :long => "--[no-]public",
84
+ :description => "Is the template public? Default: NO",
85
+ :boolean => true,
86
+ :default => false
87
+
88
+ option :passwordenabled,
89
+ :long => "--[no-]passwordenabled",
90
+ :description => "Is the password reset feature enabled, Default: YES",
91
+ :boolean => true,
92
+ :default => true
93
+
94
+ option :requireshvm,
95
+ :long => "--[no-]requireshvm",
96
+ :description => "Does the template require HVM? Default: NO",
97
+ :boolean => true,
98
+ :default => false
99
+
100
+ option :sshkeyenabled,
101
+ :long => "--[no-]sshkeyenabled",
102
+ :description => "Does this tempalte support the sshkey upload feature? Default: NO",
103
+ :boolean => true,
104
+ :default => false
105
+
106
+ def run
107
+ validate_base_options
108
+
109
+ Chef::Log.debug("Validate template name")
110
+ if locate_config_value(:name)
111
+ templatename = locate_config_value(:name)
112
+ else
113
+ templatename = @name_args.first
114
+ unless /^[a-zA-Z0-9][a-zA-Z0-9_\-# ]*$/.match templatename then
115
+ ui.error "Invalid templatename."
116
+ exit 1
117
+ end
118
+ end
119
+
120
+ unless locate_config_value(:ostypeid) then
121
+ ui.error "No os type id specified"
122
+ exit 1
123
+ end
124
+
125
+ unless /^http(s)?\:\/\//.match locate_config_value(:url) then
126
+ ui.error "URL (#{locate_config_value(:url)}) is not a well formatted url"
127
+ exit 1
128
+ end
129
+
130
+ unless (locate_config_value(:bits) == 64 or locate_config_value(:bits) == 32 ) then
131
+ ui.error "Bits must be 32 or 64"
132
+ exit 1
133
+ end
134
+
135
+ if (locate_config_value(:zone) == -1)
136
+ zoneid = -1
137
+ else
138
+ Chef::Log.debug("Resolving zone #{locate_config_value(:zone)}\n")
139
+
140
+ zone = connection.get_zone(locate_config_value(:zone))
141
+
142
+ if ! zone then
143
+ ui.error "Unable to resolve zone #{locate_config_value(:zone)}\n"
144
+ exit 1
145
+ end
146
+ zoneid = zone['id']
147
+ end
148
+
149
+ print "#{ui.color("Registring template: #{templatename}", :magenta)}\n"
150
+
151
+ params = {
152
+ 'command' => 'registerTemplate',
153
+ 'name' => templatename,
154
+ 'displaytext' => locate_config_value(:displaytext),
155
+ 'format' => locate_config_value(:format),
156
+ 'hypervisor' => locate_config_value(:hypervisor),
157
+ 'ostypeid' => locate_config_value(:ostypeid),
158
+ 'url' => locate_config_value(:url),
159
+ 'zoneid' => zoneid,
160
+ 'bits' => locate_config_value(:bits),
161
+ }
162
+ params['extracable'] = locate_config_value(:extractable) if locate_config_value(:extractable)
163
+ params['ispublic'] = locate_config_value(:public) if locate_config_value(:public)
164
+ params['isfeatured'] = locate_config_value(:featured) if locate_config_value(:featured)
165
+ params['passwordenabled'] = locate_config_value(:passwordenabled) if locate_config_value(:passwordenabled)
166
+ params['sshkeyenabled'] = locate_config_value(:sshkeyenabled) if locate_config_value(:sshkeyenabled)
167
+ params['requireshvm'] = locate_config_value(:requireshvm) if locate_config_value(:requireshvm)
168
+
169
+ json = connection.send_request(params)
170
+
171
+ if ! json then
172
+ ui.error "Template #{templatename} not registered\n"
173
+ exit 1
174
+ end
175
+
176
+ print "TemplateId #{json['template'][0]['id']} is being created\n"
177
+ end
178
+
179
+ end # class
180
+ end