Class: UpcloudApi

Inherits:
Object
  • Object
show all
Defined in:
lib/upcloud_api.rb,
lib/upcloud_api/version.rb

Overview

Class to serve as a Ruby API for the UpCloud HTTP API

Constant Summary collapse

VERSION =
"2.0.0".freeze

Instance Method Summary collapse

Constructor Details

#initialize(user, password) ⇒ UpcloudApi

Returns a new instance of UpcloudApi.

Parameters:

  • user (String)

    Upcloud API account

  • password (String)

    Upcloud API password



9
10
11
12
13
# File 'lib/upcloud_api.rb', line 9

def initialize(user, password)
  @user = user
  @password = password
  @auth = { username: @user, password: @password }
end

Instance Method Details

#account_informationObject

Returns available credits.

Calls GET /1.2/acccount

Returns available credits in the account as a string.



47
48
49
50
51
# File 'lib/upcloud_api.rb', line 47

def 
  response = get "account"
  data = JSON.parse response.body
  data["account"]["credits"]
end

#attach_storage(server_uuid, storage_uuid:, type: "disk", address: nil) ⇒ Object

Attaches a storage to a server. Server must be stopped before the storage can be attached.

Calls POST /1.2/server/server_uuid/storage/attach.

Valid values for address are: ide:[01] / scsi:0: / virtio:

to next available address.

Returns HTTParty response object.

Parameters:

  • server_uuid

    UUID of the server where the disk will be attached to.

  • storage_uuid

    UUID of the storage that will be attached.

  • type (defaults to: "disk")

    Type of the disk. Valid values are “disk” and “cdrom”.

  • address (defaults to: nil)

    Address where the disk will be attached to. Defaults



525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
# File 'lib/upcloud_api.rb', line 525

def attach_storage(server_uuid, storage_uuid:, type: "disk", address: nil)
  data = {
    "storage_device" => {
      "type" => type,
      "storage" => storage_uuid
    }
  }
  data["storage_device"]["address"] = address unless address.nil?

  json = JSON.generate data

  response = post "server/#{server_uuid}/storage/attach", json

  response
end

#clone_storage(storage_uuid, zone: "fi-hel1", title:, tier: "maxiops") ⇒ Object

Clones existing storage.

This operation is asynchronous.

Calls POST /1.2/storage/uuid/clone.

allowed value is “hdd” with the server

Returns HTTParty response object.

Parameters:

  • storage_uuid

    UUID of the storage that will be modified

  • tier (defaults to: "maxiops")

    Type of the disk. maxiops is SSD powered disk, other

  • title

    Name of the disk

  • zone (defaults to: "fi-hel1")

    Where the disk will reside. Needs to be within same zone



471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
# File 'lib/upcloud_api.rb', line 471

def clone_storage(storage_uuid, zone: "fi-hel1", title:, tier: "maxiops")
  data = {
    "storage" => {
      "zone" => zone,
      "title" => title,
      "tier" => tier
    }
  }

  json = JSON.generate data

  response = post "storage/#{storage_uuid}/clone", json

  response
end

#create_backup(storage_uuid, title:) ⇒ Object

Creates backup from a storage.

This operation is asynchronous.

Calls /1.2/storage/uuid/backup

Returns HTTParty response object.

Parameters:

  • storage_uuid

    UUID of the storage to be backed-up

  • title

    Name of the backup



574
575
576
577
578
579
580
581
582
583
584
585
586
# File 'lib/upcloud_api.rb', line 574

def create_backup(storage_uuid, title:)
  data = {
    "storage" => {
      "title" => title
    }
  }

  json = JSON.generate data

  response = post "storage/#{storage_uuid}/backup", json

  response
end

#create_server(zone: "fi-hel1", title:, hostname:, core_number: 1, memory_amount: 1024, storage_devices:, ip_addresses: :all, plan: nil, login_user: nil, other: nil) ⇒ Object

Creates new server from template.

Calls POST /1.2/server.

Storage devices should be array of hashes containing following data:

{
  "action"  => "clone"          # Can be "create", "clone" or "attach"
  "storage" => template_uuid,   # Should be passed only for "clone" or "attach"
  "title"   => disk_name,       # Name of the storage,
  "tier"    => "maxiops",       # No sense using HDD any more
}

login_user should be following hash or nil:

{
  "username": "upclouduser",
  "ssh_keys": {
    "ssh_key": [
       "ssh-rsa AAAAB3NzaC1yc2EAA[...]ptshi44x [email protected]",
       "ssh-dss AAAAB3NzaC1kc3MAA[...]VHRzAA== [email protected]"
     ]
  }
}

ip_addresses should be an array containing :public, :private and/or :ipv6. It defaults to :all, which means the server will get public IPv4, private IPv4 and public IPv6 addresses.

Returns HTTParty response object.

Parameters:

  • plan (String) (defaults to: nil)

    Preconfigured plan for the server. If nil, a custom plan will be created from input data, otherwise this overrides custom configuration. Predefined plans can be fetched with #plans.

  • other (Hash) (defaults to: nil)

    Other optional arguments create_server API call takes. See Upcloud’s documentation for possible values.



169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
# File 'lib/upcloud_api.rb', line 169

def create_server(zone: "fi-hel1", title:, hostname:, core_number: 1,
                  memory_amount: 1024, storage_devices:, ip_addresses: :all,
                  plan: nil, login_user: nil, other: nil)
  data = {
    "server" => {
      "zone" => zone,
      "title" => title,
      "hostname" => hostname,
      "storage_devices" => { "storage_device" => storage_devices }
    }
  }

  if plan.nil?
      data["server"]["core_number"] = core_number
      data["server"]["memory_amount"] = memory_amount
  else
      data["server"]["plan"] = plan
  end

  if ip_addresses != :all
    ips = []
    ips << { "access" => "public", "family" => "IPv4" } if ip_addresses.include? :public
    ips << { "access" => "private", "family" => "IPv4" } if ip_addresses.include? :private
    ips << { "access" => "public", "family" => "IPv6" } if ip_addresses.include? :ipv6

    data["server"]["ip_addresses"] = {}
    data["server"]["ip_addresses"]["ip_address"] = ips
  end

  unless .nil?
      data["login_user"] = 
  end

  unless other.nil?
      data.merge! other
  end

  json = JSON.generate data
  response = post "server", json
  response
end

#create_storage(size:, tier: "maxiops", title:, zone: "fi-hel1", backup_rule: nil) ⇒ Object

Creates new storage.

Calls POST /1.2/storage.

backup_rule should be hash with following attributes:

  • interval # allowed values: daily / mon / tue / wed / thu / fri / sat / sun

  • time # allowed values: 0000-2359

  • retention # How many days backup will be kept. Allowed values: 1-1095

allowed value is “hdd” with the server backups will be automatically created.

Returns HTTParty response object.

Parameters:

  • size

    Size of the storage in gigabytes

  • tier (defaults to: "maxiops")

    Type of the disk. maxiops is SSD powered disk, other

  • title

    Name of the disk

  • zone (defaults to: "fi-hel1")

    Where the disk will reside. Needs to be within same zone

  • backup_rule (defaults to: nil)

    Hash of backup information. If not given, no



407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
# File 'lib/upcloud_api.rb', line 407

def create_storage(size:, tier: "maxiops", title:, zone: "fi-hel1",
                   backup_rule: nil)
  data = {
    "storage" => {
      "size" => size,
      "tier" => tier,
      "title" => title,
      "zone" => zone
    }
  }
  data["storage"]["backup_rule"] = backup_rule unless backup_rule.nil?

  json = JSON.generate data
  response = post "storage", json

  response
end

#defavorite_storage(storage_uuid) ⇒ Object

Removes storage to favorites.

Calls POST /1.2/storage/storage_uuid/favorite.

Returns HTTParty response object.

Parameters:

  • storage_uuid

    UUID of the storage to be removed from favorites



623
624
625
626
627
# File 'lib/upcloud_api.rb', line 623

def defavorite_storage(storage_uuid)
  response = delete "storage/#{storage_uuid}/favorite"

  response
end

#delete_server(server_uuid) ⇒ Object

Deletes a server.

In order to delete a server, the server must be stopped first.

Calls DELETE /1.2/server/uuid.

Returns HTTParty response object.



236
237
238
239
240
# File 'lib/upcloud_api.rb', line 236

def delete_server(server_uuid)
  response = delete "server/#{server_uuid}"

  response
end

#delete_storage(storage_uuid) ⇒ Object

Deletes a storage.

The storage must be in “online” state and it must not be attached to any server. Backups will not be deleted.

Returns HTTParty response object.

Parameters:

  • storage_uuid

    UUID of the storage that will be deleted.



638
639
640
641
642
# File 'lib/upcloud_api.rb', line 638

def delete_storage(storage_uuid)
  response = delete "storage/#{storage_uuid}"

  response
end

#detach_storage(server_uuid, address:) ⇒ Object

Detaches storage from a server. Server must be stopped before the storage can be detached.

Calls POST /1.2/server/server_uuid/storage/detach.

Returns HTTParty response object.

Parameters:

  • server_uuid

    UUID of the server from which to detach the storage.

  • address

    Address where the storage that will be detached resides.



550
551
552
553
554
555
556
557
558
559
560
561
562
# File 'lib/upcloud_api.rb', line 550

def detach_storage(server_uuid, address:)
  data = {
    "storage_device" => {
      "address" => address
    }
  }

  json = JSON.generate data

  response = post "server/#{server_uuid}/storage/detach", json

  response
end

#favorite_storage(storage_uuid) ⇒ Object

Adds storage to favorites.

Calls POST /1.2/storage/storage_uuid/favorite.

Returns HTTParty response object.

Parameters:

  • storage_uuid

    UUID of the storage to be included in favorites



610
611
612
613
614
# File 'lib/upcloud_api.rb', line 610

def favorite_storage(storage_uuid)
  response = post "storage/#{storage_uuid}/favorite"

  response
end

#loginObject

Tests that authentication to Upcloud works.

This is not required to use, as authentication is used with HTTP basic auth with each request.

Calls GET /1.2/server

Returns true in success, false if not.



23
24
25
26
# File 'lib/upcloud_api.rb', line 23

def 
  response = get "server"
  response.code == 200
end

#modify_server(server_uuid, params) ⇒ Object

Modifies existing server.

In order to modify a server, the server must be stopped first.

Calls PUT /1.2/server/uuid.

Returns HTTParty response object.

Parameters:

  • server_uuid (String)

    UUID of the server that will be modified.

  • params (Hash)

    Hash of params that will be passed to be changed.



221
222
223
224
225
226
227
# File 'lib/upcloud_api.rb', line 221

def modify_server(server_uuid, params)
  data = { "server" => params }
  json = JSON.generate data
  response = put "server/#{server_uuid}", json

  response
end

#modify_storage(storage_uuid, size:, title:, backup_rule: nil) ⇒ Object

Modifies existing storage.

Calls PUT /1.2/storage/uuid.

backup_rule should be hash with following attributes:

  • interval # allowed values: daily / mon / tue / wed / thu / fri / sat / sun

  • time # allowed values: 0000-2359

  • retention # How many days backup will be kept. Allowed values: 1-1095

backups will be automatically created.

Returns HTTParty response object.

Parameters:

  • storage_uuid

    UUID of the storage that will be modified

  • size

    Size of the storage in gigabytes

  • title

    Name of the disk

  • backup_rule (defaults to: nil)

    Hash of backup information. If not given, no



441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
# File 'lib/upcloud_api.rb', line 441

def modify_storage(storage_uuid, size:, title:, backup_rule: nil)
  data = {
    "storage" => {
      "size" => size,
      "title" => title
    }
  }
  data["storage"]["backup_rule"] = backup_rule unless backup_rule.nil?

  json = JSON.generate data

  response = put "storage/#{storage_uuid}", json

  response
end

#plansObject

Lists available predefined plans that can be used to create a server.

Returns Array of plan hashes:

[
 {
   "core_number" : 1,
   "memory_amount" : 1024,
   "name" : "1xCPU-1GB",
   "public_traffic_out" : 2048,
   "storage_size" : 30,
   "storage_tier" : "maxiops"
 }
]


657
658
659
660
661
662
# File 'lib/upcloud_api.rb', line 657

def plans
  response = get "plan"

  data = JSON.parse response.body
  data["plans"]["plan"]
end

#restart_server(server_uuid, type: :soft, timeout: nil, timeout_action: :ignore) ⇒ Object

Restarts a server that is currently running.

Calls POST /1.2/server/uuid/restart.

Hard shutdown means practically same as taking the power cable off from the computer. Soft shutdown sends ACPI signal to the server, which should then automatically handle shutdown routines by itself. If timeout is given, server will be forcibly shut down after the timeout has expired.

Defaults to :soft. close cleanly. Only affects :soft type. :destroy hard stops the server and :ignore stops the operation if timeout happens. Default is :ignore.

Returns HTTParty response object.

Parameters:

  • server_uuid

    UUID of the server

  • type (defaults to: :soft)

    Type of the shutdown. Available types are :hard and :soft.

  • timeout (defaults to: nil)

    Time after server will be hard stopped if it did not

  • timeout_action (defaults to: :ignore)

    What will happen when timeout happens.



322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
# File 'lib/upcloud_api.rb', line 322

def restart_server(server_uuid, type: :soft, timeout: nil, timeout_action: :ignore)
  data = {
    "restart_server" => {
      "stop_type" => type.to_s,
      "timeout_action" => timeout_action
    }
  }
  data["restart_server"]["timeout"] = timeout unless timeout.nil?

  json = JSON.generate data

  response = post "server/#{server_uuid}/restart", json

  response
end

#restore_backup(backup_uuid) ⇒ Object

Restores a backup.

If the storage is attached to server, the server must first be stopped.

Calls /1.2/storage/backup_uuid/restore.

Returns HTTParty response object.

Parameters:

  • backup_uuid

    UUID of the backup



597
598
599
600
601
# File 'lib/upcloud_api.rb', line 597

def restore_backup(backup_uuid)
  response = post "storage/#{backup_uuid}/restore"

  response
end

#server_configurationsObject

Returns available server configurations.

Calls GET /1.2/server_size.

Returns array of server size hashes:

{
  "core_number": "1",
  "memory_amount": "512"
}


37
38
39
40
# File 'lib/upcloud_api.rb', line 37

def server_configurations
  response = get "server_size"
  response["server_sizes"]["server_size"]
end

#server_details(uuid) ⇒ Object

Shows details of a server.

Calls GET /1.2/server/uuid.

Returns hash of server details or nil:

{
 "boot_order"         => "cdrom,disk",
 "core_number"        => "3",
 "firewall"           => "off",
 "hostname"           => "dummy",
 "ip_addresses"       => {
   "ip_address" => [
     {
       "access" => "private",
       "address"            => "192.168.0.1",
      "family"             => "IPv4"
     },
     {
       "access"            => "public",
       "address"            => "::1",
       "family"             => "IPv6"
     },
     {
       "access"            => "public",
       "address"            => "198.51.100.1",
       "family"             => "IPv4"
     }
   ]
 },
 "license"            => 0,
 "memory_amount"      => "3072",
 "nic_model"          => "virtio",
 "plan"               => "custom",
 "state"              => "stopped",
 "storage_devices"    => {
   "storage_device" => [
     {
       "address" => "virtio:1",
       "storage"            => "storage_uuid",
       "storage_size"       => 10,
       "storage_title"      => "Disk name",
       "type"               => "disk"
     }
   ]
 },
 "tags"               => {"tag" => []},
 "timezone"           => "UTC",
 "title"              => "Server name",
 "uuid"               => "uuid",
 "video_model"        => "cirrus",
 "vnc"                => "off",
 "vnc_password"       => "1234",
 "zone"               => "de-fra1"
}

Parameters:

  • uuid

    from UpcloudApi#servers



127
128
129
130
131
132
133
134
# File 'lib/upcloud_api.rb', line 127

def server_details(uuid)
  response = get "server/#{uuid}"
  data = JSON.parse response.body

  return nil if data["server"].nil?

  data["server"]
end

#serversObject

Lists servers associated with the account.

Calls GET /1.2/server.

Returns array of servers with following values or empty array if no servers found.

  • zone

  • core_number

  • title

  • hostname

  • memory_amount

  • uuid

  • state



65
66
67
68
69
# File 'lib/upcloud_api.rb', line 65

def servers
  response = get "server"
  data = JSON.parse response.body
  data["servers"]["server"]
end

#start_server(server_uuid) ⇒ Object

Starts server that is shut down.

Calls POST /1.2/server/uuid/start.

Returns HTTParty response object.

Parameters:

  • server_uuid

    UUID of the server.



249
250
251
252
253
# File 'lib/upcloud_api.rb', line 249

def start_server(server_uuid)
  response = post "server/#{server_uuid}/start"

  response
end

#stop_server(server_uuid, type: :soft, timeout: nil, asynchronous: false) ⇒ Object

Shuts down a server that is currently running.

Calls POST /1.2/server/uuid/stop.

Hard shutdown means practically same as taking the power cable off from the computer. Soft shutdown sends ACPI signal to the server, which should then automatically handle shutdown routines by itself. If timeout is given, server will be forcibly shut down after the timeout has expired.

Defaults to :soft. close cleanly. Only affects :soft type. has really stopped.

Raises Timeout::Error in case server does not shut down in 300 seconds in non-asynchronous mode.

Returns HTTParty response object if server was removed successfully or request is asynchronous and nil otherwise

Parameters:

  • server_uuid

    UUID of the server

  • type (defaults to: :soft)

    Type of the shutdown. Available types are :hard and :soft.

  • timeout (defaults to: nil)

    Time after server will be hard stopped if it did not

  • asynchronous (defaults to: false)

    If false, this call will wait until the server



277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
# File 'lib/upcloud_api.rb', line 277

def stop_server(server_uuid, type: :soft, timeout: nil, asynchronous: false)
  data = {
    "stop_server" => {
      "stop_type" => type.to_s
    }
  }
  data["stop_server"]["timeout"] = timeout unless timeout.nil?

  json = JSON.generate data

  response = post "server/#{server_uuid}/stop", json

  return response if asynchronous

  Timeout.timeout 300 do
    loop do
      details = server_details server_uuid
      return response if details.nil?
      return response if details["state"] == "stopped"
    end
  end

  nil
end

#storage_details(storage_uuid) ⇒ Object

Shows detailed information of single storage.

Calls GET /1.2/storage/uuid.

Returns hash of following storage details or nil:

{
  "access"  => "public",
  "license" => 0,
  "servers" => {
      "server"=> []
    },
  "size"    => 1,
  "state"   => "online",
  "title"   => "Windows Server 2003 R2 Standard (CD 1)",
  "type"    => "cdrom",
  "uuid"    => "01000000-0000-4000-8000-000010010101"
}

Parameters:

  • storage_uuid

    UUID of the storage.



379
380
381
382
383
384
385
386
# File 'lib/upcloud_api.rb', line 379

def storage_details(storage_uuid)
  response = get "storage/#{storage_uuid}"
  data = JSON.parse response.body

  return nil if data["storage"].nil?

  data["storage"]
end

#storages(type: nil) ⇒ Object

Lists all storages or storages matching to given type.

Calls GET /1.2/storage or /1.2/storage/type.

Available types:

  • public

  • private

  • normal

  • backup

  • cdrom

  • template

  • favorite

Returns array of storages, inside “storage” key in the API or empty array if none found.

Parameters:

  • type (defaults to: nil)

    Type of the storages to be returned on nil.



354
355
356
357
358
# File 'lib/upcloud_api.rb', line 354

def storages(type: nil)
  response = get(type && "storage/#{type}" || "storage")
  data = JSON.parse response.body
  data["storages"]["storage"]
end

#templatize_storage(storage_uuid, title:) ⇒ Object

Templatizes existing storage.

This operation is asynchronous.

Calls POST /1.2/storage/uuid/templatize.

Returns HTTParty response object.

Parameters:

  • storage_uuid

    UUID of the storage that will be templatized

  • title

    Name of the template storage



497
498
499
500
501
502
503
504
505
506
507
508
509
# File 'lib/upcloud_api.rb', line 497

def templatize_storage(storage_uuid, title:)
  data = {
    "storage" => {
      "title" => title
    }
  }

  json = JSON.generate data

  response = post "storage/#{storage_uuid}/templatize", json

  response
end