Report abuse

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
#!/usr/ruby
#
# loosely based on (Tangerine ALPHA ) by Isam M (r0cketjump YAHOO COM)  [his code was useful :-)]
#
# ZoneParser was created by Ben Congleton from Hab.la (http://www.hab.la) and Nethernet Consulting (http://www.nethernet.com)
#
#
# I recommend using Zone Parser to import your zones from your normal DNS server,
# and then Isam's Tangerine to deal with them once their in slicehost.


require 'rubygems'
require 'activeresource'

API_PASSWORD = 'API_KEY_HERE' 
API_ADDRESS = "https://#{API_PASSWORD}@api.slicehost.com/" 
NAMESERVERS = ["ns1.slicehost.com", "ns2.slicehost.com", "ns3.slicehost.com"]
VERBOSE = true
DEBUG   = false

class Zone < ActiveResource::Base
    self.site = API_ADDRESS
end

class Record < ActiveResource::Base
    self.site = API_ADDRESS
end



class ZoneParser
  attr_accessor :records
  attr_accessor :domain
  def initialize(filename, domain)
    @records = Array.new
    @domain  = domain

    File.open(filename, 'r').each_line do |line|
      next if (line =~ /SOA/)
      next if (line =~ /^\s*\;/)
      parts = line.split(/\s\s*/)
      next if (parts.size == 0)
      next if ( (parts.first == "" or parts.first == "@") && !parts[1].match(/^\D\D*$/) )
      next if (parts[1] == "NS") # no need for NS records
      p line if (DEBUG)

      if(parts.first == "" or parts.first == "@" )
        parts[0] = domain + "."
      end

      if(parts[1] == "IN")
        parts = [parts[0], parts[2], parts[3], parts[4..parts.size].join(" ")]
      end

      ap = {
        :record_type => parts[1], 
        :name => parts[0], 
        :data => parts.last, 
        :ttl => 8000, 
        :active => 'Y', 
        :aux => 0
      }
      if(parts.size == 4)
        ap[:aux] = parts[2]
      end
      p ap if(DEBUG)

      #p parts
      #p ap
      #p line
      @records << ap
    end
  end

  def sync(clear = true)
    # syncronizes the web-based zone from the file-based zone.
    z = Zone.find(:first, :params => {'origin' => @domain + "."})
    p z if(DEBUG)

    if( not z):
      z = Zone.new({ 
          :origin => @domain, 
          :ttl => 8000, 
          :active => 'Y' 
      })
      z.save unless z.nil? 
    end

    if(not z)
      raise Exception.new("Error finding/creating zone for #{@domain}")
    elsif(VERBOSE)
      print "Syncing Zone: #{@domain}\n"
    end

    p z if(DEBUG)

    # ok at this point we have a zone.
    # wipe it
    if(clear)
      print "\nRemoving all records for zone: #{@domain}\n" if(VERBOSE)
      Record.find(:all, :params => {:zone_id => z.id}).each do |r|
        r.destroy unless r.nil? 
        p r if (DEBUG)
        print "\t- #{r.name} #{r.record_type} #{r.data}\n" if(VERBOSE)
      end
    end
    print "\nAdding records to zone: #{@domain}\n" if(VERBOSE)

    # add the Nameservers:
    base = {
      :record_type => "NS", 
      :name => @domain + ".", 
      :ttl => 8000, 
      :active => 'Y', 
      :aux => 0
    }
    NAMESERVERS.each do |ns|
      base[:data] = ns  
      @records << base.dup
    end

    # add the zones
    @records.each do |r|
      r[:zone_id] = z.id
      rec = Record.new(r)
      rec.save unless rec.nil?

      if(not rec or rec.errors.size > 0)
        print "\t* ERROR ADDING #{r[:name]} #{r[:record_type]} #{r[:data]}\n"
        p rec
      elsif(rec && VERBOSE)
        p rec if(DEBUG)
        print "\t+ #{r[:name]} #{r[:record_type]} #{r[:data]}\n" 
      end     



    end

  end

end #end class



z = ZoneParser.new("test_zone.txt", "hab.la")

z.sync



=begin
;
;This is an example test zone
;
@        IN SOA    ns1.netherweb.com. ben.nethernet.com. (
                2008102701
              3600   ; refresh [1h]
              3600   ; retry   [1h]
              6H   ; expire  [2h]
             3H)  ; minimum [1d]

                NS      ns1.netherweb.com.
                NS      ns2.netherweb.com.

@               A       216.9.83.199
                MX      1 ASPMX.L.GOOGLE.COM.
                MX      5 ALT1.ASPMX.L.GOOGLE.COM.
                MX      5 ALT2.ASPMX.L.GOOGLE.COM.
                MX      10 ASPMX2.GOOGLEMAIL.COM.
                MX      10 ASPMX3.GOOGLEMAIL.COM.
                MX      10 ASPMX4.GOOGLEMAIL.COM.
                MX      10 ASPMX5.GOOGLEMAIL.COM.                                                              
www             A       216.9.83.199
*.async         A       216.9.83.197
*.aync          A       216.9.83.197

_jabber._tcp.staging       IN SRV   0 0 18269   staging.hab.la.
_xmpp-server._tcp.staging  IN SRV   0 0 18269   staging.hab.la.
_xmpp-client._tcp.staging  IN SRV   0 0 18222   staging.hab.la.


=end