Skip to content

Commit

Permalink
Merge branch 'CHEF-1267'
Browse files Browse the repository at this point in the history
  • Loading branch information
danielsdeleo committed Jun 11, 2010
2 parents 9812e90 + 4873060 commit eeaba65
Show file tree
Hide file tree
Showing 6 changed files with 400 additions and 3 deletions.
9 changes: 6 additions & 3 deletions chef/lib/chef/platform.rb
Expand Up @@ -132,23 +132,26 @@ def platforms
:env => Chef::Provider::Env::Windows,
:service => Chef::Provider::Service::Windows,
:user => Chef::Provider::User::Windows,
:group => Chef::Provider::Group::Windows
:group => Chef::Provider::Group::Windows,
:mount => Chef::Provider::Mount::Windows
}
},
:mingw32 => {
:default => {
:env => Chef::Provider::Env::Windows,
:service => Chef::Provider::Service::Windows,
:user => Chef::Provider::User::Windows,
:group => Chef::Provider::Group::Windows
:group => Chef::Provider::Group::Windows,
:mount => Chef::Provider::Mount::Windows
}
},
:windows => {
:default => {
:env => Chef::Provider::Env::Windows,
:service => Chef::Provider::Service::Windows,
:user => Chef::Provider::User::Windows,
:group => Chef::Provider::Group::Windows
:group => Chef::Provider::Group::Windows,
:mount => Chef::Provider::Mount::Windows
}
},
:solaris => {},
Expand Down
80 changes: 80 additions & 0 deletions chef/lib/chef/provider/mount/windows.rb
@@ -0,0 +1,80 @@
#
# Author:: Doug MacEachern (<dougm@vmware.com>)
# Copyright:: Copyright (c) 2010 VMware, Inc.
# License:: Apache License, Version 2.0
#
# 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.
#

require 'chef/provider/mount'
if RUBY_PLATFORM =~ /mswin|mingw32|windows/
require 'chef/util/windows/net_use'
require 'chef/util/windows/volume'
end

class Chef
class Provider
class Mount
class Windows < Chef::Provider::Mount

def is_volume(name)
name =~ /^\\\\\?\\Volume\{[\w-]+\}\\$/ ? true : false
end

def initialize(new_resource, run_context)
super
@mount = nil
end

def load_current_resource
if is_volume(@new_resource.device)
@mount = Chef::Util::Windows::Volume.new(@new_resource.name)
else #assume network drive
@mount = Chef::Util::Windows::NetUse.new(@new_resource.name)
end

@current_resource = Chef::Resource::Mount.new(@new_resource.name)
@current_resource.mount_point(@new_resource.mount_point)
Chef::Log.debug("Checking for mount point #{@current_resource.mount_point}")

begin
@current_resource.device(@mount.device)
Chef::Log.debug("#{@current_resource.device} mounted on #{@new_resource.mount_point}")
@current_resource.mounted(true)
rescue ArgumentError => e
@current_resource.mounted(false)
Chef::Log.debug("#{@new_resource.mount_point} is not mounted: #{e.message}")
end
end

def mount_fs
unless @current_resource.mounted
@mount.add(@new_resource.device)
else
Chef::Log.debug("#{@new_resource.mount_point} is already mounted.")
end
end

def umount_fs
if @current_resource.mounted
@mount.delete
Chef::Log.info("Unmounted #{@new_resource.mount_point}")
else
Chef::Log.debug("#{@new_resource.mount_point} is not mounted.")
end
end

end
end
end
end
1 change: 1 addition & 0 deletions chef/lib/chef/providers.rb
Expand Up @@ -82,6 +82,7 @@
require 'chef/provider/group/windows'

require 'chef/provider/mount/mount'
require 'chef/provider/mount/windows'

require 'chef/provider/deploy/revision'
require 'chef/provider/deploy/timestamped'
121 changes: 121 additions & 0 deletions chef/lib/chef/util/windows/net_use.rb
@@ -0,0 +1,121 @@
#
# Author:: Doug MacEachern (<dougm@vmware.com>)
# Copyright:: Copyright (c) 2010 VMware, Inc.
# License:: Apache License, Version 2.0
#
# 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.
#

#the Win32 Volume APIs do not support mapping network drives. not supported by WMI either.
#see also: WNetAddConnection2 and WNetAddConnection3
#see also cmd.exe: net use /?

require 'chef/util/windows'

class Chef::Util::Windows::NetUse < Chef::Util::Windows

private

USE_NOFORCE = 0
USE_FORCE = 1
USE_LOTS_OF_FORCE = 2 #every windows API should support this flag

USE_INFO_2 = [
[:local, nil],
[:remote, nil],
[:password, nil],
[:status, 0],
[:asg_type, 0],
[:refcount, 0],
[:usecount, 0],
[:username, nil],
[:domainname, nil]
]

USE_INFO_2_TEMPLATE =
USE_INFO_2.collect { |field| field[1].class == Fixnum ? 'i' : 'L' }.join

SIZEOF_USE_INFO_2 = #sizeof(USE_INFO_2)
USE_INFO_2.inject(0){|sum,item|
sum + (item[1].class == Fixnum ? 4 : PTR_SIZE)
}

def use_info_2(args)
USE_INFO_2.collect { |field|
args.include?(field[0]) ? args[field[0]] : field[1]
}
end

def use_info_2_pack(use)
use.collect { |v|
v.class == Fixnum ? v : str_to_ptr(multi_to_wide(v))
}.pack(USE_INFO_2_TEMPLATE)
end

def use_info_2_unpack(buffer)
use = Hash.new
USE_INFO_2.each_with_index do |field,offset|
use[field[0]] = field[1].class == Fixnum ?
dword_to_i(buffer, offset) : lpwstr_to_s(buffer, offset)
end
use
end

public

def initialize(localname)
@localname = localname
@name = multi_to_wide(localname)
end

def add(args)
if args.class == String
remote = args
args = Hash.new(USE_INFO_2)
args[:remote] = remote
end
args[:local] ||= @localname
use = use_info_2(args)
buffer = use_info_2_pack(use)
rc = NetUseAdd.call(nil, 2, buffer, nil)
if rc != NERR_Success
raise ArgumentError, get_last_error(rc)
end
end

def get_info
ptr = 0.chr * PTR_SIZE
rc = NetUseGetInfo.call(nil, @name, 2, ptr)

if rc != NERR_Success
raise ArgumentError, get_last_error(rc)
end

ptr = ptr.unpack('L')[0]
buffer = 0.chr * SIZEOF_USE_INFO_2
memcpy(buffer, ptr, buffer.size)
NetApiBufferFree(ptr)
use_info_2_unpack(buffer)
end

def device
get_info()[:remote]
end
#XXX should we use some FORCE here?
def delete
rc = NetUseDel.call(nil, @name, USE_NOFORCE)
if rc != NERR_Success
raise ArgumentError, get_last_error(rc)
end
end
end
59 changes: 59 additions & 0 deletions chef/lib/chef/util/windows/volume.rb
@@ -0,0 +1,59 @@
#
# Author:: Doug MacEachern (<dougm@vmware.com>)
# Copyright:: Copyright (c) 2010 VMware, Inc.
# License:: Apache License, Version 2.0
#
# 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.
#

#simple wrapper around Volume APIs. might be possible with WMI, but possibly more complex.

require 'chef/util/windows'
require 'windows/volume'

class Chef::Util::Windows::Volume < Chef::Util::Windows

private
include Windows::Volume
#XXX not defined in the current windows-pr release
DeleteVolumeMountPoint =
Windows::API.new('DeleteVolumeMountPoint', 'S', 'B') unless defined? DeleteVolumeMountPoint

public

def initialize(name)
name += "\\" unless name =~ /\\$/ #trailing slash required
@name = name
end

def device
buffer = 0.chr * 256
if GetVolumeNameForVolumeMountPoint(@name, buffer, buffer.size)
return buffer[0,buffer.size].unpack("Z*")[0]
else
raise ArgumentError, get_last_error
end
end

def delete
unless DeleteVolumeMountPoint.call(@name)
raise ArgumentError, get_last_error
end
end

def add(device)
unless SetVolumeMountPoint(@name, device)
raise ArgumentError, get_last_error
end
end
end

0 comments on commit eeaba65

Please sign in to comment.