knife-cloudstack 0.0.13 → 0.0.14

Sign up to get free protection for your applications and to get access to all the features.
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