right_link 5.9.0

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 (199) hide show
  1. data/actors/agent_manager.rb +88 -0
  2. data/actors/instance_scheduler.rb +321 -0
  3. data/actors/instance_services.rb +64 -0
  4. data/actors/instance_setup.rb +567 -0
  5. data/bin/cloud +25 -0
  6. data/bin/cook_runner +44 -0
  7. data/bin/deploy +120 -0
  8. data/bin/enroll +385 -0
  9. data/bin/rad +32 -0
  10. data/bin/rchk +29 -0
  11. data/bin/rnac +39 -0
  12. data/bin/rs_connect +33 -0
  13. data/bin/rs_log_level +31 -0
  14. data/bin/rs_ohai +28 -0
  15. data/bin/rs_reenroll +31 -0
  16. data/bin/rs_run_recipe +34 -0
  17. data/bin/rs_run_right_script +34 -0
  18. data/bin/rs_shutdown +33 -0
  19. data/bin/rs_tag +33 -0
  20. data/bin/rs_thunk +33 -0
  21. data/bin/rstat +31 -0
  22. data/bin/system +16 -0
  23. data/ext/Rakefile +18 -0
  24. data/init/config.yml +5 -0
  25. data/init/init.rb +79 -0
  26. data/lib/chef/ohai_setup.rb +51 -0
  27. data/lib/chef/plugins/cloud.rb +91 -0
  28. data/lib/chef/plugins/cloudstack.rb +23 -0
  29. data/lib/chef/plugins/ec2.rb +23 -0
  30. data/lib/chef/plugins/linux/block_device2.rb +24 -0
  31. data/lib/chef/plugins/rackspace.rb +23 -0
  32. data/lib/chef/plugins/rightscale.rb +125 -0
  33. data/lib/chef/plugins/windows/network.rb +114 -0
  34. data/lib/chef/plugins.rb +74 -0
  35. data/lib/chef/providers/dns_dnsmadeeasy_provider.rb +81 -0
  36. data/lib/chef/providers/dns_resource.rb +100 -0
  37. data/lib/chef/providers/executable_schedule_provider.rb +70 -0
  38. data/lib/chef/providers/executable_schedule_resource.rb +144 -0
  39. data/lib/chef/providers/remote_recipe_provider.rb +86 -0
  40. data/lib/chef/providers/remote_recipe_resource.rb +101 -0
  41. data/lib/chef/providers/right_link_tag_provider.rb +73 -0
  42. data/lib/chef/providers/right_link_tag_resource.rb +59 -0
  43. data/lib/chef/providers/right_script_provider.rb +190 -0
  44. data/lib/chef/providers/right_script_resource.rb +113 -0
  45. data/lib/chef/providers/rs_shutdown_provider.rb +75 -0
  46. data/lib/chef/providers/rs_shutdown_resource.rb +55 -0
  47. data/lib/chef/providers/server_collection_provider.rb +66 -0
  48. data/lib/chef/providers/server_collection_resource.rb +93 -0
  49. data/lib/chef/providers/windows/powershell_provider.rb +151 -0
  50. data/lib/chef/providers/windows/powershell_resource.rb +111 -0
  51. data/lib/chef/providers/windows/unsupported_provider.rb +51 -0
  52. data/lib/chef/right_providers.rb +55 -0
  53. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/ChefNodeCmdlet.csproj +104 -0
  54. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/ChefNodeCmdlet.dll-Help.xml +141 -0
  55. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/Exceptions.cs +182 -0
  56. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetChefNodeCommand.cs +58 -0
  57. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetChefNodeRequest.cs +46 -0
  58. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetChefNodeResponse.cs +45 -0
  59. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetCurrentResourceCommand.cs +58 -0
  60. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetCurrentResourceRequest.cs +46 -0
  61. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetCurrentResourceResponse.cs +45 -0
  62. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetNewResourceCommand.cs +58 -0
  63. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetNewResourceRequest.cs +46 -0
  64. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetNewResourceResponse.cs +45 -0
  65. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetNextActionCommand.cs +178 -0
  66. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetNextActionRequest.cs +67 -0
  67. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetNextActionResponse.cs +58 -0
  68. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetNodeValueCommandBase.cs +142 -0
  69. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetNodeValueRequestBase.cs +64 -0
  70. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetNodeValueResponseBase.cs +69 -0
  71. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/JsonTransport.cs +110 -0
  72. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/PipeClient.cs +158 -0
  73. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/PipeServer.cs +142 -0
  74. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/Properties/AssemblyInfo.cs +16 -0
  75. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/ProtocolConstants.cs +55 -0
  76. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/ProtocolUtilities.cs +77 -0
  77. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/ReadMe.txt +53 -0
  78. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetChefNodeCommand.cs +59 -0
  79. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetChefNodeRequest.cs +46 -0
  80. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetChefNodeResponse.cs +58 -0
  81. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetCurrentResourceCommand.cs +59 -0
  82. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetCurrentResourceRequest.cs +46 -0
  83. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetCurrentResourceResponse.cs +40 -0
  84. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetNewResourceCommand.cs +59 -0
  85. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetNewResourceRequest.cs +46 -0
  86. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetNewResourceResponse.cs +40 -0
  87. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetNodeValueCommandBase.cs +293 -0
  88. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetNodeValueRequestBase.cs +75 -0
  89. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetNodeValueResponseBase.cs +45 -0
  90. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/Transport.cs +91 -0
  91. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet.sln +35 -0
  92. data/lib/chef/windows/ChefNodeCmdlet/TestChefNodeCmdlet/Program.cs +374 -0
  93. data/lib/chef/windows/ChefNodeCmdlet/TestChefNodeCmdlet/Properties/AssemblyInfo.cs +16 -0
  94. data/lib/chef/windows/ChefNodeCmdlet/TestChefNodeCmdlet/TestChefNodeCmdlet.csproj +65 -0
  95. data/lib/chef/windows/ChefNodeCmdlet/TestNextActionCmdlet/Program.cs +136 -0
  96. data/lib/chef/windows/ChefNodeCmdlet/TestNextActionCmdlet/Properties/AssemblyInfo.cs +36 -0
  97. data/lib/chef/windows/ChefNodeCmdlet/TestNextActionCmdlet/ReadMe.txt +46 -0
  98. data/lib/chef/windows/ChefNodeCmdlet/TestNextActionCmdlet/TestNextActionCmdlet.csproj +68 -0
  99. data/lib/chef/windows/bin/Newtonsoft.Json.dll +0 -0
  100. data/lib/chef/windows/chef_node_server.rb +463 -0
  101. data/lib/chef/windows/dynamic_powershell_provider.rb +296 -0
  102. data/lib/chef/windows/pipe_server.rb +283 -0
  103. data/lib/chef/windows/powershell_host.rb +285 -0
  104. data/lib/chef/windows/powershell_pipe_server.rb +136 -0
  105. data/lib/chef/windows/powershell_provider_base.rb +92 -0
  106. data/lib/chef/windows/scripts/run_loop.ps1 +105 -0
  107. data/lib/clouds/cloud.rb +557 -0
  108. data/lib/clouds/cloud_factory.rb +250 -0
  109. data/lib/clouds/cloud_utilities.rb +244 -0
  110. data/lib/clouds/clouds/azure.rb +106 -0
  111. data/lib/clouds/clouds/cloudstack.rb +114 -0
  112. data/lib/clouds/clouds/ec2.rb +113 -0
  113. data/lib/clouds/clouds/eucalyptus.rb +46 -0
  114. data/lib/clouds/clouds/google.rb +102 -0
  115. data/lib/clouds/clouds/none.rb +76 -0
  116. data/lib/clouds/clouds/openstack.rb +30 -0
  117. data/lib/clouds/clouds/rackspace-ng.rb +54 -0
  118. data/lib/clouds/clouds/rackspace.rb +78 -0
  119. data/lib/clouds/clouds/softlayer.rb +91 -0
  120. data/lib/clouds/metadata_formatter.rb +108 -0
  121. data/lib/clouds/metadata_provider.rb +128 -0
  122. data/lib/clouds/metadata_source.rb +87 -0
  123. data/lib/clouds/metadata_sources/certificate_metadata_source.rb +207 -0
  124. data/lib/clouds/metadata_sources/config_drive_metadata_source.rb +129 -0
  125. data/lib/clouds/metadata_sources/file_metadata_source.rb +74 -0
  126. data/lib/clouds/metadata_sources/http_metadata_source.rb +277 -0
  127. data/lib/clouds/metadata_sources/selective_metadata_source.rb +122 -0
  128. data/lib/clouds/metadata_tree_climber.rb +144 -0
  129. data/lib/clouds/metadata_writer.rb +155 -0
  130. data/lib/clouds/metadata_writers/dictionary_metadata_writer.rb +72 -0
  131. data/lib/clouds/metadata_writers/ruby_metadata_writer.rb +76 -0
  132. data/lib/clouds/metadata_writers/shell_metadata_writer.rb +121 -0
  133. data/lib/clouds/register_clouds.rb +34 -0
  134. data/lib/clouds.rb +32 -0
  135. data/lib/gem_dependencies.rb +83 -0
  136. data/lib/git_hooks/commit-msg.rb +7 -0
  137. data/lib/instance/agent_config.rb +168 -0
  138. data/lib/instance/agent_watcher.rb +233 -0
  139. data/lib/instance/audit_cook_stub.rb +104 -0
  140. data/lib/instance/audit_proxy.rb +247 -0
  141. data/lib/instance/bundle_queue.rb +104 -0
  142. data/lib/instance/cook/agent_connection.rb +109 -0
  143. data/lib/instance/cook/audit_logger.rb +165 -0
  144. data/lib/instance/cook/audit_stub.rb +142 -0
  145. data/lib/instance/cook/ca-bundle.crt +2794 -0
  146. data/lib/instance/cook/chef_state.rb +211 -0
  147. data/lib/instance/cook/cook.rb +306 -0
  148. data/lib/instance/cook/cook_state.rb +298 -0
  149. data/lib/instance/cook/cookbook_path_mapping.rb +66 -0
  150. data/lib/instance/cook/cookbook_repo_retriever.rb +190 -0
  151. data/lib/instance/cook/executable_sequence.rb +765 -0
  152. data/lib/instance/cook/external_parameter_gatherer.rb +190 -0
  153. data/lib/instance/cook/repose_downloader.rb +349 -0
  154. data/lib/instance/cook/shutdown_request_proxy.rb +121 -0
  155. data/lib/instance/cook.rb +41 -0
  156. data/lib/instance/downloader.rb +208 -0
  157. data/lib/instance/duplicable.rb +67 -0
  158. data/lib/instance/exceptions.rb +49 -0
  159. data/lib/instance/executable_sequence_proxy.rb +278 -0
  160. data/lib/instance/instance_commands.rb +577 -0
  161. data/lib/instance/instance_state.rb +633 -0
  162. data/lib/instance/json_utilities.rb +102 -0
  163. data/lib/instance/login_manager.rb +533 -0
  164. data/lib/instance/login_user_manager.rb +522 -0
  165. data/lib/instance/message_encoder.rb +118 -0
  166. data/lib/instance/multi_thread_bundle_queue.rb +232 -0
  167. data/lib/instance/operation_context.rb +60 -0
  168. data/lib/instance/options_bag.rb +65 -0
  169. data/lib/instance/payload_formatter.rb +46 -0
  170. data/lib/instance/policy.rb +53 -0
  171. data/lib/instance/policy_audit.rb +100 -0
  172. data/lib/instance/policy_manager.rb +146 -0
  173. data/lib/instance/reenroll_manager.rb +104 -0
  174. data/lib/instance/right_scripts_cookbook.rb +181 -0
  175. data/lib/instance/shutdown_request.rb +221 -0
  176. data/lib/instance/single_thread_bundle_queue.rb +189 -0
  177. data/lib/instance/volume_management.rb +450 -0
  178. data/lib/instance.rb +50 -0
  179. data/lib/repo_conf_generators/apt_conf_generators.rb +106 -0
  180. data/lib/repo_conf_generators/gem_conf_generators.rb +80 -0
  181. data/lib/repo_conf_generators/rightscale_conf_generators.rb +254 -0
  182. data/lib/repo_conf_generators/rightscale_key.pub +17 -0
  183. data/lib/repo_conf_generators/yum_conf_generators.rb +225 -0
  184. data/lib/repo_conf_generators.rb +30 -0
  185. data/lib/run_shell.rb +28 -0
  186. data/scripts/agent_checker.rb +571 -0
  187. data/scripts/agent_controller.rb +247 -0
  188. data/scripts/agent_deployer.rb +148 -0
  189. data/scripts/bundle_runner.rb +336 -0
  190. data/scripts/cloud_controller.rb +176 -0
  191. data/scripts/log_level_manager.rb +142 -0
  192. data/scripts/ohai_runner.rb +33 -0
  193. data/scripts/reenroller.rb +193 -0
  194. data/scripts/server_importer.rb +293 -0
  195. data/scripts/shutdown_client.rb +183 -0
  196. data/scripts/system_configurator.rb +367 -0
  197. data/scripts/tagger.rb +381 -0
  198. data/scripts/thunker.rb +356 -0
  199. metadata +418 -0
@@ -0,0 +1,114 @@
1
+ #
2
+ # Copyright (c) 2011 RightScale Inc
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+
23
+ # set abbreviation for env var generation to be same as ec2 for scripters.
24
+ abbreviation :ec2
25
+
26
+ # Searches for a file containing dhcp lease information.
27
+ def dhcp_lease_provider
28
+ if platform.windows?
29
+ timeout = Time.now + 20 * 60 # 20 minutes
30
+ logger = option(:logger)
31
+ while Time.now < timeout
32
+ ipconfig_data = `ipconfig /all`
33
+ match_result = ipconfig_data.match(/DHCP Server.*\: (\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})/)
34
+ unless match_result.nil? || match_result[1].nil?
35
+ return match_result[1]
36
+ end
37
+ # it may take time to resolve the DHCP Server for this instance, so sleepy wait.
38
+ logger.info("ipconfig /all did not contain any DHCP Servers. Retrying in 10 seconds...")
39
+ sleep 10
40
+ end
41
+ else
42
+ leases_file = %w{/var/lib/dhcp/dhclient.eth0.leases /var/lib/dhcp3/dhclient.eth0.leases /var/lib/dhclient/dhclient-eth0.leases /var/lib/dhclient-eth0.leases /var/lib/dhcpcd/dhcpcd-eth0.info}.find{|dhcpconfig| File.exist?(dhcpconfig)}
43
+ unless leases_file.nil?
44
+ lease_file_content = File.read(leases_file)
45
+
46
+ dhcp_lease_provider_ip = lease_file_content[/DHCPSID='(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})'/, 1]
47
+ return dhcp_lease_provider_ip unless dhcp_lease_provider_ip.nil?
48
+
49
+ # leases are appended to the lease file, so to get the appropriate dhcp lease provider, we must grab
50
+ # the info from the last lease entry.
51
+ #
52
+ # reverse the content and reverse the regex to find the dhcp lease provider from the last lease entry
53
+ lease_file_content.reverse!
54
+ dhcp_lease_provider_ip = lease_file_content[/(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}) reifitnedi-revres-pchd/, 1]
55
+ return dhcp_lease_provider_ip.reverse unless dhcp_lease_provider_ip.nil?
56
+ end
57
+ end
58
+
59
+ # no known defaults so we must fail at this point.
60
+ fail("Cannot determine dhcp lease provider for cloudstack instance")
61
+ end
62
+
63
+ # set default hosts before extending ec2. avoid search for dhcp lease provider
64
+ # in case host was given explicitly.
65
+ unless option('metadata_source/hosts')
66
+ default_option('metadata_source/hosts', [{:host => dhcp_lease_provider, :port => 80}])
67
+ end
68
+
69
+ # cloud metadata root differs from EC2 (user use the same).
70
+ default_option(:cloud_metadata_root_path, "latest")
71
+
72
+ # cloudstack cloud metadata cannot query the list of values at root but instead
73
+ # relies on a predefined list.
74
+ default_option('cloud_metadata/metadata_provider/query_override', lambda do |provider, path|
75
+ if path.chomp('/') == provider.metadata_tree_climber.root_path
76
+ leaf_names = %w{service-offering availability-zone local-ipv4 local-hostname public-ipv4 public-hostname instance-id}
77
+ return leaf_names.join("\n")
78
+ end
79
+ return provider.metadata_source.query(path)
80
+ end)
81
+
82
+ # override metadata soures. Using only HTTP source
83
+ metadata_source 'metadata_sources/http_metadata_source'
84
+
85
+ # extend EC2 cloud definition.
86
+ extend_cloud :ec2
87
+
88
+ # Determines if the current instance is running on cloudstack.
89
+ def is_current_cloud?
90
+ # FIX: the following cloud check needs to be strengthened since it the result
91
+ # returned true even when not on a cloud instance. non-distinctive cloud
92
+ # checks make automatic cloud detection impossible (not a critical feature,
93
+ # but it's nice-to-have).
94
+ #
95
+ # it is usually possible to open a connection to the DHCP server (anonymous
96
+ # authentication fails but the connection is established). perhaps
97
+ # successfully retrieving some minimal metadata from the service?. is it
98
+ # possible instead to do a has_mac? check here like some other clouds?
99
+ #
100
+ # anyway, better to return false instead of erroneously detecting cloudstack.
101
+ #
102
+ # source = create_dependency_type(:user_metadata, :metadata_source)
103
+ # return ::RightScale::CloudUtilities.can_contact_metadata_server?(source.host, source.port)
104
+ false
105
+ end
106
+
107
+ # Updates details of cloudstack instance.
108
+ def update_details
109
+ details = {}
110
+ hosts = option('metadata_source/hosts')
111
+ # do not resolve the dhcp lease providr again. just get it from the cloud host option
112
+ details[:dhcp_lease_provider_ip] = hosts.first[:host]
113
+ return details
114
+ end
@@ -0,0 +1,113 @@
1
+ #
2
+ # Copyright (c) 2011 RightScale Inc
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+
23
+ # host/port are constants for EC2.
24
+ HOST = '169.254.169.254'
25
+ PORT = 80
26
+ SHEBANG_REGEX = /^#!/
27
+
28
+ # dependencies.
29
+ metadata_source 'metadata_sources/selective_metadata_source'
30
+ metadata_writers 'metadata_writers/dictionary_metadata_writer',
31
+ 'metadata_writers/ruby_metadata_writer',
32
+ 'metadata_writers/shell_metadata_writer'
33
+
34
+ # Assembles the command line needed to regenerate cloud metadata on demand.
35
+ def cloud_metadata_generation_command
36
+ ruby_path = File.normalize_path(AgentConfig.ruby_cmd)
37
+ rs_cloud_path = File.normalize_path(Gem.bin_path('right_link', 'cloud'))
38
+ return "#{ruby_path} #{rs_cloud_path} --action write_cloud_metadata"
39
+ end
40
+
41
+ # Selects metadata from multiple sources in support of serverizing existing
42
+ # long-running instances. Stops merging metadata as soon as RS_ variables
43
+ # are found.
44
+ def select_rs_metadata(_, path, metadata_source_type, query_result, previous_metadata)
45
+ # note that clouds can extend this cloud and change the user root option.
46
+ @cached_user_metadata_root_path = option([:user_metadata, :metadata_tree_climber, :root_path]) unless @cached_user_metadata_root_path
47
+ query_next_metadata = false
48
+ merged_metadata = query_result
49
+ if path == @cached_user_metadata_root_path
50
+ # metadata from file source is delimited by newline while metadata from http
51
+ # is delimited by ampersand (unless shebang is present for legacy reasons).
52
+ # convert ampersand-delimited to newline-delimited for easier comparison
53
+ # with regular expression.
54
+ previous_metadata.strip!
55
+ query_result.strip!
56
+ if (metadata_source_type == 'metadata_sources/file_metadata_source') || (query_result =~ SHEBANG_REGEX)
57
+ current_metadata = query_result.gsub("\r\n", "\n").strip
58
+ else
59
+ current_metadata = query_result.gsub("&", "\n").strip
60
+ end
61
+
62
+ # will query next source only if current metadata does not contain RS_
63
+ query_next_metadata = !(current_metadata =~ /^RS_rn_id/i)
64
+ merged_metadata = (previous_metadata + "\n" + current_metadata).strip
65
+ merged_metadata = merged_metadata.gsub("\n", "&") unless merged_metadata =~ SHEBANG_REGEX
66
+ end
67
+ return {:query_next_metadata => query_next_metadata, :merged_metadata => merged_metadata}
68
+ end
69
+
70
+ # Parses ec2 user metadata into a hash.
71
+ #
72
+ # === Parameters
73
+ # tree_climber(MetadataTreeClimber):: tree climber
74
+ # data(String):: raw data
75
+ #
76
+ # === Return
77
+ # result(Hash):: Hash-like leaf value
78
+ def create_user_metadata_leaf(tree_climber, data)
79
+ result = tree_climber.create_branch
80
+ data = data.strip
81
+ if data =~ SHEBANG_REGEX
82
+ ::RightScale::CloudUtilities.split_metadata(data.gsub("\r\n", "\n"), "\n", result)
83
+ else
84
+ ::RightScale::CloudUtilities.split_metadata(data, '&', result)
85
+ end
86
+ result
87
+ end
88
+
89
+ # defaults
90
+ default_option([:metadata_source, :hosts], [:host => HOST, :port => PORT])
91
+ default_option([:metadata_source, :metadata_source_types], ['metadata_sources/http_metadata_source', 'metadata_sources/file_metadata_source'])
92
+ default_option([:metadata_source, :select_metadata_override], method(:select_rs_metadata))
93
+ default_option([:metadata_source, :user_metadata_source_file_path], File.join(RightScale::Platform.filesystem.spool_dir, name.to_s, 'user-data.txt'))
94
+
95
+ default_option(:cloud_metadata_root_path, 'latest/meta-data')
96
+ default_option([:cloud_metadata, :metadata_writers, :ruby_metadata_writer, :generation_command], cloud_metadata_generation_command)
97
+
98
+ default_option(:user_metadata_root_path, 'latest/user-data')
99
+ default_option([:user_metadata, :metadata_tree_climber, :create_leaf_override], method(:create_user_metadata_leaf))
100
+
101
+ # Determines if the current instance is running on the EC2.
102
+ #
103
+ # === Return
104
+ # true if running on EC2
105
+ def is_current_cloud?
106
+ if ohai = @options[:ohai_node]
107
+ if ::RightScale::CloudUtilities.has_mac?(ohai, "fe:ff:ff:ff:ff:ff")
108
+ source = create_dependency_type(:user_metadata, :metadata_source)
109
+ return ::RightScale::CloudUtilities.can_contact_metadata_server?(source.host, source.port)
110
+ end
111
+ end
112
+ false
113
+ end
@@ -0,0 +1,46 @@
1
+ #
2
+ # Copyright (c) 2011 RightScale Inc
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+
23
+ # eucalyptus can use any DNS name for host but port is known and we are
24
+ # constrained to requiring a specific DNS name by default.
25
+ EUCA_HOST = 'euca-metadata'
26
+ EUCA_PORT = 8773
27
+
28
+ # set abbreviation for env var generation to be same as ec2 for scripters.
29
+ abbreviation :ec2
30
+
31
+ # preserve any initial hosts option.
32
+ initial_hosts = option('metadata_source/hosts')
33
+
34
+ # override metadata soures. Using only HTTP source
35
+ metadata_source 'metadata_sources/http_metadata_source'
36
+
37
+ # extend EC2 cloud definition.
38
+ extend_cloud :ec2
39
+
40
+ # defaults.
41
+ unless initial_hosts
42
+ # eucalyptus hosts supercede ec2 hosts in search order.
43
+ metadata_source_options = default_option(:metadata_source, {})
44
+ ec2_hosts = metadata_source_options[:hosts] || []
45
+ metadata_source_options[:hosts] = [:host => EUCA_HOST, :port => EUCA_PORT] + ec2_hosts
46
+ end
@@ -0,0 +1,102 @@
1
+ #
2
+ # Copyright (c) 2012 RightScale Inc
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+
23
+ # host/port are constants for Google Compute Engine.
24
+ HOST = 'metadata'
25
+ PORT = 80
26
+
27
+ abbreviation :gce
28
+
29
+ # defaults
30
+ metadata_source 'metadata_sources/http_metadata_source'
31
+ metadata_writers 'metadata_writers/dictionary_metadata_writer',
32
+ 'metadata_writers/ruby_metadata_writer',
33
+ 'metadata_writers/shell_metadata_writer'
34
+
35
+ default_option([:metadata_source, :hosts], [:host => HOST, :port => PORT])
36
+
37
+ # root paths, don't leave off the trailing slashes
38
+ default_option([:cloud_metadata, :metadata_tree_climber, :root_path], '0.1/meta-data/')
39
+ default_option([:user_metadata, :metadata_tree_climber, :root_path], '0.1/meta-data/attributes/')
40
+
41
+ default_option([:cloud_metadata, :metadata_provider, :query_override], lambda do |provider, path|
42
+ # auth token will return an error if we try to query
43
+ result = provider.metadata_source.query(path)
44
+ result = result.split("\n").select { |t| t !~ /auth.token/ }.join("\n")
45
+ # filter out userdata for consitency with other clouds
46
+ if path == provider.metadata_tree_climber.root_path
47
+ result = result.split("\n").select { |t| t != 'attributes/' }.join("\n")
48
+ end
49
+ return result
50
+ end)
51
+
52
+ default_option([:user_metadata, :metadata_tree_climber, :has_children_override], lambda do |climber, path, query_result|
53
+ # for ec2, metadata is a single value, for GCE, its a tree, override this
54
+ # function so we'll recurse down
55
+ return path =~ /\/$/
56
+ end)
57
+
58
+
59
+ # Determines if the current instance is running on GCE
60
+ #
61
+ # === Return
62
+ # true if running on GCE
63
+ def is_current_cloud?
64
+ # See https://developers.google.com/compute/docs/instances#dmi
65
+ `grep Google /sys/firmware/dmi/entries/1-0/raw 2>&1 >/dev/null`
66
+ return $?.success?
67
+ end
68
+
69
+ # Provides details of the google cloud for inclusion in the cloud node.
70
+ #
71
+ # === Return
72
+ # always true
73
+ def update_details
74
+ details = {}
75
+ if ohai = @options[:ohai_node]
76
+ # the 'network' key from cloud metadata contains a JSONized hash with the
77
+ # public/private IP details.
78
+ # example:
79
+ # ohai[:google][:network] = "{\"networkInterface\":[{\"network\":\"projects/12345/networks/default\",\"ip\":\"10.11.12.13\",\"accessConfiguration\":[{\"type\":\"ONE_TO_ONE_NAT\",\"externalIp\":\"123.4.5.6\"}]}]}"
80
+ public_ip = nil
81
+ private_ip = nil
82
+ if named_cloud_node = ohai[self.name.to_s.to_sym]
83
+ begin
84
+ network_json = named_cloud_node["network"]
85
+ network_data = JSON.load(network_json)
86
+ if network_interface = network_data['networkInterface'] && network_data['networkInterface'].first
87
+ private_ip = network_interface['ip']
88
+ if access_configuration = network_interface['accessConfiguration'] && network_interface['accessConfiguration'].first
89
+ public_ip = access_configuration['externalIp']
90
+ end
91
+ else
92
+ logger.warn("No network interfaces found in #{self.name} network metadata")
93
+ end
94
+ rescue Exception => e
95
+ logger.warn("Unable to parse #{self.name} network metadata from #{network_json.inspect}\n#{e.class}: #{e.message}")
96
+ end
97
+ end
98
+ details[:public_ip] = public_ip if public_ip
99
+ details[:private_ip] = private_ip if private_ip
100
+ end
101
+ return details
102
+ end
@@ -0,0 +1,76 @@
1
+ #
2
+ # Copyright (c) 2011 RightScale Inc
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+
23
+ # dependencies.
24
+ metadata_source 'metadata_sources/file_metadata_source'
25
+ metadata_writers 'metadata_writers/dictionary_metadata_writer',
26
+ 'metadata_writers/ruby_metadata_writer',
27
+ 'metadata_writers/shell_metadata_writer'
28
+
29
+ # set abbreviation for non-RS env var generation (not actually used by this cloud)
30
+ abbreviation :none
31
+
32
+ # Parses no-cloud user metadata into a hash.
33
+ #
34
+ # === Parameters
35
+ # tree_climber(MetadataTreeClimber):: tree climber
36
+ # data(String):: raw data
37
+ #
38
+ # === Return
39
+ # result(Hash):: Hash-like leaf value
40
+ def create_user_metadata_leaf(tree_climber, data)
41
+ result = tree_climber.create_branch
42
+ ::RightScale::CloudUtilities.split_metadata(data, "\n", result)
43
+ result
44
+ end
45
+
46
+ # defaults.
47
+ default_option([:user_metadata, :metadata_tree_climber, :create_leaf_override], method(:create_user_metadata_leaf))
48
+ default_option([:metadata_source, :user_metadata_source_file_path], File.join(RightScale::Platform.filesystem.spool_dir, name.to_s, 'user-data.txt'))
49
+
50
+ # Determines if the current instance is running in the "none" cloud. This is a bit
51
+ # circular, as it simply checks the contents of the cloud-file.
52
+ #
53
+ # === Return
54
+ # true if running on none cloud
55
+ def is_current_cloud?
56
+ cloud_file = RightScale::AgentConfig.cloud_file_path
57
+ return !!(File.readable?(cloud_file) && File.read(cloud_file) =~ /none/)
58
+ end
59
+
60
+ # Updates the given node with no-cloud details.
61
+ #
62
+ # === Return
63
+ # always true
64
+ def update_details
65
+ details = {}
66
+ if ohai = @options[:ohai_node]
67
+ if platform.windows?
68
+ details[:public_ip] = ::RightScale::CloudUtilities.ip_for_windows_interface(ohai, 'public')
69
+ details[:private_ip] = ::RightScale::CloudUtilities.ip_for_windows_interface(ohai, 'private')
70
+ else
71
+ details[:public_ip] = ::RightScale::CloudUtilities.ip_for_interface(ohai, :eth0)
72
+ details[:private_ip] = ::RightScale::CloudUtilities.ip_for_interface(ohai, :eth1)
73
+ end
74
+ end
75
+ return details
76
+ end
@@ -0,0 +1,30 @@
1
+ #
2
+ # Copyright (c) 2011 RightScale Inc
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+
23
+ # set abbreviation for env var generation to be same as ec2 for scripters.
24
+ abbreviation :ec2
25
+
26
+ # override metadata soures. Using only HTTP source
27
+ metadata_source 'metadata_sources/http_metadata_source'
28
+
29
+ # extend EC2 cloud definition.
30
+ extend_cloud :ec2
@@ -0,0 +1,54 @@
1
+ #
2
+ # Copyright (c) 2012-2013 RightScale Inc
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+
23
+ # set abbreviation for env var generation to be same as legacy Rackspace for scripters.
24
+ abbreviation :rax
25
+
26
+ # extend legacy Rackspace cloud definition. currently there are no differences aside from name.
27
+ extend_cloud :rackspace
28
+
29
+ # Updates the given node with cloudstack details.
30
+ #
31
+ # === Return
32
+ # always true
33
+ def update_details
34
+ details = {}
35
+ if ohai = @options[:ohai_node]
36
+ if platform.windows?
37
+ details[:public_ip] = ::RightScale::CloudUtilities.ip_for_windows_interface(ohai, 'public')
38
+ details[:private_ip] = ::RightScale::CloudUtilities.ip_for_windows_interface(ohai, 'private')
39
+ else
40
+ details[:public_ip] = ::RightScale::CloudUtilities.ip_for_interface(ohai, :eth0)
41
+ details[:private_ip] = ::RightScale::CloudUtilities.ip_for_interface(ohai, :eth1)
42
+ end
43
+ end
44
+
45
+ # rack_connect (and managed?) instances may not have network interfaces for
46
+ # public ip, so attempt the "what's my ip?" method in these cases.
47
+ unless details[:public_ip]
48
+ if public_ip = ::RightScale::CloudUtilities.query_whats_my_ip(:logger=>logger)
49
+ details[:public_ip] = public_ip
50
+ end
51
+ end
52
+
53
+ return details
54
+ end
@@ -0,0 +1,78 @@
1
+ #
2
+ # Copyright (c) 2011 RightScale Inc
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+
23
+ # dependencies.
24
+ metadata_source 'metadata_sources/file_metadata_source'
25
+ metadata_writers 'metadata_writers/dictionary_metadata_writer',
26
+ 'metadata_writers/ruby_metadata_writer',
27
+ 'metadata_writers/shell_metadata_writer'
28
+
29
+ # set abbreviation for non-RS env var generation
30
+ abbreviation :rax
31
+
32
+ # Parses rackspace user metadata into a hash.
33
+ #
34
+ # === Parameters
35
+ # tree_climber(MetadataTreeClimber):: tree climber
36
+ # data(String):: raw data
37
+ #
38
+ # === Return
39
+ # result(Hash):: Hash-like leaf value
40
+ def create_user_metadata_leaf(tree_climber, data)
41
+ result = tree_climber.create_branch
42
+ ::RightScale::CloudUtilities.split_metadata(data.strip, "\n", result)
43
+ result
44
+ end
45
+
46
+ # defaults.
47
+ default_option([:user_metadata, :metadata_tree_climber, :create_leaf_override], method(:create_user_metadata_leaf))
48
+ default_option([:metadata_source, :user_metadata_source_file_path], File.join(RightScale::Platform.filesystem.spool_dir, name.to_s, 'user-data.txt'))
49
+
50
+ # Determines if the current instance is running on rackspace.
51
+ #
52
+ # === Return
53
+ # true if running on rackspace
54
+ def is_current_cloud?
55
+ if ohai = @options[:ohai_node]
56
+ return true if ::RightScale::CloudUtilities.has_mac?(ohai, "00:00:0c:07:ac:01")
57
+ return ohai[:kernel] && ohai[:kernel][:release].to_s.split('-').last.eql?("rscloud")
58
+ end
59
+ false
60
+ end
61
+
62
+ # Updates the given node with cloudstack details.
63
+ #
64
+ # === Return
65
+ # always true
66
+ def update_details
67
+ details = {}
68
+ if ohai = @options[:ohai_node]
69
+ if platform.windows?
70
+ details[:public_ip] = ::RightScale::CloudUtilities.ip_for_windows_interface(ohai, 'public')
71
+ details[:private_ip] = ::RightScale::CloudUtilities.ip_for_windows_interface(ohai, 'private')
72
+ else
73
+ details[:public_ip] = ::RightScale::CloudUtilities.ip_for_interface(ohai, :eth0)
74
+ details[:private_ip] = ::RightScale::CloudUtilities.ip_for_interface(ohai, :eth1)
75
+ end
76
+ end
77
+ return details
78
+ end