github.com/1and1/oneandone-cloudserver-sdk-go@v1.4.1/servers.go (about)

     1  package oneandone
     2  
     3  import (
     4  	"encoding/json"
     5  	"errors"
     6  	"math/big"
     7  	"net/http"
     8  )
     9  
    10  type Server struct {
    11  	ApiPtr
    12  	Identity
    13  	descField
    14  	CreationDate  string                 `json:"creation_date,omitempty"`
    15  	FirstPassword string                 `json:"first_password,omitempty"`
    16  	ServerType    string                 `json:"server_type,omitempty"`
    17  	Ipv6Range     string                 `json:"ipv6_range,omitempty"`
    18  	Hostname      string                 `json:"hostname,omitempty"`
    19  	Datacenter    *Datacenter            `json:"datacenter,omitempty"`
    20  	Status        *Status                `json:"status,omitempty"`
    21  	Hardware      *Hardware              `json:"hardware,omitempty"`
    22  	Image         *Identity              `json:"image,omitempty"`
    23  	Dvd           *Identity              `json:"dvd,omitempty"`
    24  	MonPolicy     *Identity              `json:"monitoring_policy,omitempty"`
    25  	Snapshot      *ServerSnapshot        `json:"snapshot,omitempty"`
    26  	Ips           []ServerIp             `json:"ips,omitempty"`
    27  	PrivateNets   []ServerPrivateNetwork `json:"private_networks,omitempty"`
    28  	Alerts        *ServerAlerts          `json:"-"`
    29  	AlertsRaw     *json.RawMessage       `json:"alerts,omitempty"`
    30  }
    31  
    32  type Hardware struct {
    33  	Vcores            int         `json:"vcore,omitempty"`
    34  	CoresPerProcessor int         `json:"cores_per_processor"`
    35  	Ram               float32     `json:"ram"`
    36  	Hdds              []Hdd       `json:"hdds,omitempty"`
    37  	FixedInsSizeId    string      `json:"fixed_instance_size_id,omitempty"`
    38  	BaremetalModelId  interface{} `json:"baremetal_model_id,omitempty"`
    39  	ApiPtr
    40  }
    41  
    42  type ServerHdds struct {
    43  	Hdds []Hdd `json:"hdds,omitempty"`
    44  }
    45  
    46  type Hdd struct {
    47  	idField
    48  	Size   int    `json:"size,omitempty"`
    49  	IsMain bool   `json:"is_main"`
    50  	Unit   string `json:"unit,omitempty"`
    51  	ApiPtr
    52  }
    53  
    54  type serverDeployImage struct {
    55  	idField
    56  	Password string    `json:"password,omitempty"`
    57  	Firewall *Identity `json:"firewall_policy,omitempty"`
    58  }
    59  
    60  type ServerPrivateNetwork struct {
    61  	Identity
    62  	ServerIP string `json:"server_ip,omitempty"`
    63  }
    64  
    65  type ServerIp struct {
    66  	idField
    67  	typeField
    68  	Ip            string     `json:"ip,omitempty"`
    69  	ReverseDns    string     `json:"reverse_dns,omitempty"`
    70  	Firewall      *Identity  `json:"firewall_policy,omitempty"`
    71  	LoadBalancers []Identity `json:"load_balancers,omitempty"`
    72  	ApiPtr
    73  }
    74  
    75  type ServerIpInfo struct {
    76  	idField           // IP id
    77  	Ip         string `json:"ip,omitempty"`
    78  	ServerName string `json:"server_name,omitempty"`
    79  }
    80  
    81  type ServerSnapshot struct {
    82  	idField
    83  	CreationDate string `json:"creation_date,omitempty"`
    84  	DeletionDate string `json:"deletion_date,omitempty"`
    85  }
    86  
    87  type ServerAlerts struct {
    88  	AlertSummary []serverAlertSummary
    89  	AlertDetails *serverAlertDetails
    90  }
    91  
    92  type serverAlertSummary struct {
    93  	countField
    94  	typeField
    95  }
    96  
    97  type serverAlertDetails struct {
    98  	Criticals []ServerAlert `json:"critical,omitempty"`
    99  	Warnings  []ServerAlert `json:"warning,omitempty"`
   100  }
   101  
   102  type ServerAlert struct {
   103  	typeField
   104  	descField
   105  	Date string `json:"date"`
   106  }
   107  
   108  type ServerRequest struct {
   109  	Name               string   `json:"name,omitempty"`
   110  	Description        string   `json:"description,omitempty"`
   111  	Hardware           Hardware `json:"hardware"`
   112  	ApplianceId        string   `json:"appliance_id,omitempty"`
   113  	Password           string   `json:"password,omitempty"`
   114  	ServerType         string   `json:"server_type,omitempty"`
   115  	Ipv6Range          string   `json:"ipv6_range,omitempty"`
   116  	Hostname           string   `json:"hostname,omitempty"`
   117  	PowerOn            bool     `json:"power_on"`
   118  	FirewallPolicyId   string   `json:"firewall_policy_id,omitempty"`
   119  	IpId               string   `json:"ip_id,omitempty"`
   120  	LoadBalancerId     string   `json:"load_balancer_id,omitempty"`
   121  	MonitoringPolicyId string   `json:"monitoring_policy_id,omitempty"`
   122  	DatacenterId       string   `json:"datacenter_id,omitempty"`
   123  	SSHKey             string   `json:"rsa_key,omitempty"`
   124  	SSHPassword        *bool    `json:"ssh_password,omitempty"`
   125  	PublicKey          []string `json:"public_key,omitempty"`
   126  	PrivateNetworkId   string   `json:"private_network_id,omitempty"`
   127  }
   128  
   129  type ServerAction struct {
   130  	Action          string  `json:"action,omitempty"`
   131  	Method          string  `json:"method,omitempty"`
   132  	RecoveryMode    *bool   `json:"recovery_mode,omitempty"`
   133  	RecoveryImageId *string `json:"recovery_image_id,omitempty"`
   134  }
   135  
   136  type FixedInstanceInfo struct {
   137  	Identity
   138  	Hardware *Hardware `json:"hardware,omitempty"`
   139  	ApiPtr
   140  }
   141  
   142  type BaremetalModel struct {
   143  	ApiPtr
   144  	Identity
   145  	descField
   146  	Hardware *BaremetalHardware `json:"hardware,omitempty"`
   147  }
   148  
   149  type BaremetalHardware struct {
   150  	Cores             int     `json:"core,omitempty"`
   151  	CoresPerProcessor int     `json:"cores_per_processor"`
   152  	Ram               float32 `json:"ram"`
   153  	Unit              string  `json:"unit,omitempty"`
   154  	Hdds              []Hdd     `json:"hdds,omitempty"`
   155  	ApiPtr
   156  }
   157  
   158  // GET /servers
   159  func (api *API) ListServers(args ...interface{}) ([]Server, error) {
   160  	url, err := processQueryParams(createUrl(api, serverPathSegment), args...)
   161  	if err != nil {
   162  		return nil, err
   163  	}
   164  	result := []Server{}
   165  	err = api.Client.Get(url, &result, http.StatusOK)
   166  	if err != nil {
   167  		return nil, err
   168  	}
   169  	for _, s := range result {
   170  		s.api = api
   171  		s.decodeRaws()
   172  	}
   173  	return result, nil
   174  }
   175  
   176  // POST /servers
   177  func (api *API) CreateServer(request *ServerRequest) (string, *Server, error) {
   178  	result := new(Server)
   179  	url := createUrl(api, serverPathSegment)
   180  	err := api.Client.Post(url, &request, &result, http.StatusAccepted)
   181  	if err != nil {
   182  		return "", nil, err
   183  	}
   184  	result.api = api
   185  	result.decodeRaws()
   186  	return result.Id, result, nil
   187  }
   188  
   189  // This is a wrapper function for `CreateServer` that returns the server's IP address and first password.
   190  // The function waits at most `timeout` seconds for the server to be created.
   191  // The initial `POST /servers` response does not contain the IP address, so we need to wait
   192  // until the server is created.
   193  func (api *API) CreateServerEx(request *ServerRequest, timeout int) (string, string, error) {
   194  	id, server, err := api.CreateServer(request)
   195  	if server != nil && err == nil {
   196  		count := timeout / 5
   197  		if request.PowerOn {
   198  			err = api.WaitForState(server, "POWERED_ON", 5, count)
   199  		} else {
   200  			err = api.WaitForState(server, "POWERED_OFF", 5, count)
   201  		}
   202  		if err != nil {
   203  			return "", "", err
   204  		}
   205  		server, err := api.GetServer(id)
   206  		if server != nil && err == nil && server.Ips[0].Ip != "" {
   207  			if server.FirstPassword != "" {
   208  				return server.Ips[0].Ip, server.FirstPassword, nil
   209  			}
   210  			if request.Password != "" {
   211  				return server.Ips[0].Ip, request.Password, nil
   212  			}
   213  			// should never reach here
   214  			return "", "", errors.New("No server's password was found.")
   215  		}
   216  	}
   217  	return "", "", err
   218  }
   219  
   220  // GET /servers/{id}
   221  func (api *API) GetServer(server_id string) (*Server, error) {
   222  	result := new(Server)
   223  	url := createUrl(api, serverPathSegment, server_id)
   224  	err := api.Client.Get(url, &result, http.StatusOK)
   225  	if err != nil {
   226  		return nil, err
   227  	}
   228  	result.api = api
   229  	result.decodeRaws()
   230  	return result, nil
   231  }
   232  
   233  // GET /servers/fixed_instance_sizes
   234  func (api *API) ListFixedInstanceSizes() ([]FixedInstanceInfo, error) {
   235  	result := []FixedInstanceInfo{}
   236  	url := createUrl(api, serverPathSegment, "fixed_instance_sizes")
   237  	err := api.Client.Get(url, &result, http.StatusOK)
   238  	if err != nil {
   239  		return nil, err
   240  	}
   241  	for index, _ := range result {
   242  		result[index].api = api
   243  	}
   244  	return result, nil
   245  }
   246  
   247  // GET /servers/fixed_instance_sizes/{fixed_instance_size_id}
   248  func (api *API) GetFixedInstanceSize(fis_id string) (*FixedInstanceInfo, error) {
   249  	result := new(FixedInstanceInfo)
   250  	url := createUrl(api, serverPathSegment, "fixed_instance_sizes", fis_id)
   251  	err := api.Client.Get(url, &result, http.StatusOK)
   252  	if err != nil {
   253  		return nil, err
   254  	}
   255  	result.api = api
   256  	return result, nil
   257  }
   258  
   259  // DELETE /servers/{id}
   260  func (api *API) DeleteServer(server_id string, args ...interface{}) (*Server, error) {
   261  	result := new(Server)
   262  	url := createUrl(api, serverPathSegment, server_id)
   263  
   264  	var keep_ips, keep_hdds, is_true bool
   265  	pm := make(map[string]interface{}, len(args))
   266  	for i, p := range args {
   267  		switch i {
   268  		case 0:
   269  			keep_ips, is_true = p.(bool)
   270  			if !is_true {
   271  				return nil, errors.New("1st parameter is keep_ips must be a bool")
   272  			} else {
   273  				pm["keep_ips"] = keep_ips
   274  			}
   275  		case 1:
   276  			keep_hdds, is_true = p.(bool)
   277  			if !is_true {
   278  				return nil, errors.New("2nd parameter is keep_hdds must be a bool")
   279  			} else {
   280  				pm["keep_hdds"] = keep_hdds
   281  			}
   282  		}
   283  	}
   284  
   285  	url = appendQueryParams(url, pm)
   286  	err := api.Client.Delete(url, nil, &result, http.StatusAccepted)
   287  	if err != nil {
   288  		return nil, err
   289  	}
   290  	result.api = api
   291  	result.decodeRaws()
   292  	return result, nil
   293  }
   294  
   295  // PUT /servers/{id}
   296  func (api *API) RenameServer(server_id string, new_name string, new_desc string) (*Server, error) {
   297  	data := struct {
   298  		Name        string `json:"name,omitempty"`
   299  		Description string `json:"description,omitempty"`
   300  	}{Name: new_name, Description: new_desc}
   301  	result := new(Server)
   302  	url := createUrl(api, serverPathSegment, server_id)
   303  	err := api.Client.Put(url, &data, &result, http.StatusOK)
   304  	if err != nil {
   305  		return nil, err
   306  	}
   307  	result.api = api
   308  	result.decodeRaws()
   309  	return result, nil
   310  }
   311  
   312  // GET /servers/{server_id}/hardware
   313  func (api *API) GetServerHardware(server_id string) (*Hardware, error) {
   314  	result := new(Hardware)
   315  	url := createUrl(api, serverPathSegment, server_id, "hardware")
   316  	err := api.Client.Get(url, &result, http.StatusOK)
   317  	if err != nil {
   318  		return nil, err
   319  	}
   320  	result.api = api
   321  	return result, nil
   322  }
   323  
   324  // PUT /servers/{server_id}/hardware
   325  func (api *API) UpdateServerHardware(server_id string, hardware *Hardware) (*Server, error) {
   326  	var vc, cpp *int
   327  	var ram *float32
   328  	if hardware.Vcores > 0 {
   329  		vc = new(int)
   330  		*vc = hardware.Vcores
   331  	}
   332  	if hardware.CoresPerProcessor > 0 {
   333  		cpp = new(int)
   334  		*cpp = hardware.CoresPerProcessor
   335  	}
   336  	if big.NewFloat(float64(hardware.Ram)).Cmp(big.NewFloat(0)) != 0 {
   337  		ram = new(float32)
   338  		*ram = hardware.Ram
   339  	}
   340  	req := struct {
   341  		VCores *int     `json:"vcore,omitempty"`
   342  		Cpp    *int     `json:"cores_per_processor,omitempty"`
   343  		Ram    *float32 `json:"ram,omitempty"`
   344  		Flavor string   `json:"fixed_instance_size_id,omitempty"`
   345  	}{VCores: vc, Cpp: cpp, Ram: ram, Flavor: hardware.FixedInsSizeId}
   346  
   347  	result := new(Server)
   348  	url := createUrl(api, serverPathSegment, server_id, "hardware")
   349  	err := api.Client.Put(url, &req, &result, http.StatusAccepted)
   350  	if err != nil {
   351  		return nil, err
   352  	}
   353  	result.api = api
   354  	result.decodeRaws()
   355  	return result, nil
   356  }
   357  
   358  // GET /servers/{id}/hardware/hdds
   359  func (api *API) ListServerHdds(server_id string) ([]Hdd, error) {
   360  	result := []Hdd{}
   361  	url := createUrl(api, serverPathSegment, server_id, "hardware/hdds")
   362  	err := api.Client.Get(url, &result, http.StatusOK)
   363  	if err != nil {
   364  		return nil, err
   365  	}
   366  	for index, _ := range result {
   367  		result[index].api = api
   368  	}
   369  	return result, nil
   370  }
   371  
   372  // POST /servers/{id}/hardware/hdds
   373  func (api *API) AddServerHdds(server_id string, hdds *ServerHdds) (*Server, error) {
   374  	result := new(Server)
   375  	url := createUrl(api, serverPathSegment, server_id, "hardware/hdds")
   376  	err := api.Client.Post(url, &hdds, &result, http.StatusAccepted)
   377  	if err != nil {
   378  		return nil, err
   379  	}
   380  	result.api = api
   381  	result.decodeRaws()
   382  	return result, nil
   383  }
   384  
   385  // GET /servers/{id}/hardware/hdds/{id}
   386  func (api *API) GetServerHdd(server_id string, hdd_id string) (*Hdd, error) {
   387  	result := new(Hdd)
   388  	url := createUrl(api, serverPathSegment, server_id, "hardware/hdds", hdd_id)
   389  	err := api.Client.Get(url, &result, http.StatusOK)
   390  	if err != nil {
   391  		return nil, err
   392  	}
   393  	result.api = api
   394  	return result, nil
   395  }
   396  
   397  // DELETE /servers/{id}/hardware/hdds/{id}
   398  func (api *API) DeleteServerHdd(server_id string, hdd_id string) (*Server, error) {
   399  	result := new(Server)
   400  	url := createUrl(api, serverPathSegment, server_id, "hardware/hdds", hdd_id)
   401  	err := api.Client.Delete(url, nil, &result, http.StatusAccepted)
   402  	if err != nil {
   403  		return nil, err
   404  	}
   405  	result.api = api
   406  	result.decodeRaws()
   407  	return result, nil
   408  }
   409  
   410  // PUT /servers/{id}/hardware/hdds/{id}
   411  func (api *API) ResizeServerHdd(server_id string, hdd_id string, new_size int) (*Server, error) {
   412  	data := Hdd{Size: new_size}
   413  	result := new(Server)
   414  	url := createUrl(api, serverPathSegment, server_id, "hardware/hdds", hdd_id)
   415  	err := api.Client.Put(url, &data, &result, http.StatusAccepted)
   416  	if err != nil {
   417  		return nil, err
   418  	}
   419  	result.api = api
   420  	result.decodeRaws()
   421  	return result, nil
   422  }
   423  
   424  // GET /servers/{id}/image
   425  func (api *API) GetServerImage(server_id string) (*Identity, error) {
   426  	result := new(Identity)
   427  	url := createUrl(api, serverPathSegment, server_id, "image")
   428  	err := api.Client.Get(url, &result, http.StatusOK)
   429  	if err != nil {
   430  		return nil, err
   431  	}
   432  	return result, nil
   433  }
   434  
   435  // PUT /servers/{id}/image
   436  func (api *API) ReinstallServerImage(server_id string, image_id string, password string, fp_id string) (*Server, error) {
   437  	data := new(serverDeployImage)
   438  	data.Id = image_id
   439  	data.Password = password
   440  	if fp_id != "" {
   441  		fp := new(Identity)
   442  		fp.Id = fp_id
   443  		data.Firewall = fp
   444  	}
   445  
   446  	result := new(Server)
   447  	url := createUrl(api, serverPathSegment, server_id, "image")
   448  	err := api.Client.Put(url, &data, &result, http.StatusAccepted)
   449  	if err != nil {
   450  		return nil, err
   451  	}
   452  	result.api = api
   453  	result.decodeRaws()
   454  	return result, nil
   455  }
   456  
   457  // GET /servers/{id}/ips
   458  func (api *API) ListServerIps(server_id string) ([]ServerIp, error) {
   459  	result := []ServerIp{}
   460  	url := createUrl(api, serverPathSegment, server_id, "ips")
   461  	err := api.Client.Get(url, &result, http.StatusOK)
   462  	if err != nil {
   463  		return nil, err
   464  	}
   465  	for index, _ := range result {
   466  		result[index].api = api
   467  	}
   468  	return result, nil
   469  }
   470  
   471  // POST /servers/{id}/ips
   472  func (api *API) AssignServerIp(server_id string, ip_type string) (*Server, error) {
   473  	data := typeField{Type: ip_type}
   474  	result := new(Server)
   475  	url := createUrl(api, serverPathSegment, server_id, "ips")
   476  	err := api.Client.Post(url, &data, &result, http.StatusCreated)
   477  	if err != nil {
   478  		return nil, err
   479  	}
   480  	result.api = api
   481  	result.decodeRaws()
   482  	return result, nil
   483  }
   484  
   485  // GET /servers/{id}/ips/{id}
   486  func (api *API) GetServerIp(server_id string, ip_id string) (*ServerIp, error) {
   487  	result := new(ServerIp)
   488  	url := createUrl(api, serverPathSegment, server_id, "ips", ip_id)
   489  	err := api.Client.Get(url, &result, http.StatusOK)
   490  	if err != nil {
   491  		return nil, err
   492  	}
   493  	result.api = api
   494  	return result, nil
   495  }
   496  
   497  // DELETE /servers/{id}/ips/{id}
   498  func (api *API) DeleteServerIp(server_id string, ip_id string, keep_ip bool) (*Server, error) {
   499  	result := new(Server)
   500  	url := createUrl(api, serverPathSegment, server_id, "ips", ip_id)
   501  	qm := make(map[string]interface{}, 1)
   502  	qm["keep_ip"] = keep_ip
   503  	url = appendQueryParams(url, qm)
   504  	err := api.Client.Delete(url, nil, &result, http.StatusAccepted)
   505  	if err != nil {
   506  		return nil, err
   507  	}
   508  	result.api = api
   509  	return result, nil
   510  }
   511  
   512  // GET /servers/{id}/status
   513  func (api *API) GetServerStatus(server_id string) (*Status, error) {
   514  	result := new(Status)
   515  	url := createUrl(api, serverPathSegment, server_id, "status")
   516  	err := api.Client.Get(url, &result, http.StatusOK)
   517  	if err != nil {
   518  		return nil, err
   519  	}
   520  	return result, nil
   521  }
   522  
   523  // PUT /servers/{id}/status/action (action = REBOOT)
   524  func (api *API) RebootServer(server_id string, is_hardware bool) (*Server, error) {
   525  	result := new(Server)
   526  	request := ServerAction{}
   527  	request.Action = "REBOOT"
   528  	if is_hardware {
   529  		request.Method = "HARDWARE"
   530  	} else {
   531  		request.Method = "SOFTWARE"
   532  	}
   533  	url := createUrl(api, serverPathSegment, server_id, "status", "action")
   534  	err := api.Client.Put(url, &request, &result, http.StatusAccepted)
   535  	if err != nil {
   536  		return nil, err
   537  	}
   538  	result.api = api
   539  	result.decodeRaws()
   540  	return result, nil
   541  }
   542  
   543  // PUT /servers/{id}/status/action (action = REBOOT)
   544  func (api *API) RecoveryRebootServer(server_id string, is_hardware bool, recovery_image_id string) (*Server, error) {
   545  	result := new(Server)
   546  	request := ServerAction{}
   547  	request.Action = "REBOOT"
   548  	if is_hardware {
   549  		request.Method = "HARDWARE"
   550  	} else {
   551  		request.Method = "SOFTWARE"
   552  	}
   553  
   554  	b := true
   555  	request.RecoveryMode = &b
   556  	request.RecoveryImageId = &recovery_image_id
   557  	url := createUrl(api, serverPathSegment, server_id, "status", "action")
   558  	err := api.Client.Put(url, &request, &result, http.StatusAccepted)
   559  	if err != nil {
   560  		return nil, err
   561  	}
   562  	result.api = api
   563  	result.decodeRaws()
   564  	return result, nil
   565  }
   566  
   567  // PUT /servers/{id}/status/action (action = POWER_OFF)
   568  func (api *API) ShutdownServer(server_id string, is_hardware bool) (*Server, error) {
   569  	result := new(Server)
   570  	request := ServerAction{}
   571  	request.Action = "POWER_OFF"
   572  	if is_hardware {
   573  		request.Method = "HARDWARE"
   574  	} else {
   575  		request.Method = "SOFTWARE"
   576  	}
   577  	url := createUrl(api, serverPathSegment, server_id, "status", "action")
   578  	err := api.Client.Put(url, &request, &result, http.StatusAccepted)
   579  	if err != nil {
   580  		return nil, err
   581  	}
   582  	result.api = api
   583  	result.decodeRaws()
   584  	return result, nil
   585  }
   586  
   587  // PUT /servers/{id}/status/action (action = POWER_ON)
   588  func (api *API) StartServer(server_id string) (*Server, error) {
   589  	result := new(Server)
   590  	request := ServerAction{}
   591  	request.Action = "POWER_ON"
   592  	url := createUrl(api, serverPathSegment, server_id, "status", "action")
   593  	err := api.Client.Put(url, &request, &result, http.StatusAccepted)
   594  	if err != nil {
   595  		return nil, err
   596  	}
   597  	result.api = api
   598  	result.decodeRaws()
   599  	return result, nil
   600  }
   601  
   602  // GET /servers/{id}/dvd
   603  func (api *API) GetServerDvd(server_id string) (*Identity, error) {
   604  	result := new(Identity)
   605  	url := createUrl(api, serverPathSegment, server_id, "dvd")
   606  	err := api.Client.Get(url, &result, http.StatusOK)
   607  	if err != nil {
   608  		return nil, err
   609  	}
   610  	return result, nil
   611  }
   612  
   613  // DELETE /servers/{id}/dvd
   614  func (api *API) EjectServerDvd(server_id string) (*Server, error) {
   615  	result := new(Server)
   616  	url := createUrl(api, serverPathSegment, server_id, "dvd")
   617  	err := api.Client.Delete(url, nil, &result, http.StatusAccepted)
   618  	if err != nil {
   619  		return nil, err
   620  	}
   621  	result.api = api
   622  	result.decodeRaws()
   623  	return result, nil
   624  }
   625  
   626  // PUT /servers/{id}/dvd
   627  func (api *API) LoadServerDvd(server_id string, dvd_id string) (*Server, error) {
   628  	request := Identity{}
   629  	request.Id = dvd_id
   630  	result := new(Server)
   631  	url := createUrl(api, serverPathSegment, server_id, "dvd")
   632  	err := api.Client.Put(url, &request, &result, http.StatusAccepted)
   633  	if err != nil {
   634  		return nil, err
   635  	}
   636  	result.api = api
   637  	result.decodeRaws()
   638  	return result, nil
   639  }
   640  
   641  // GET /servers/{id}/private_networks
   642  func (api *API) ListServerPrivateNetworks(server_id string) ([]Identity, error) {
   643  	result := []Identity{}
   644  	url := createUrl(api, serverPathSegment, server_id, "private_networks")
   645  	err := api.Client.Get(url, &result, http.StatusOK)
   646  	if err != nil {
   647  		return nil, err
   648  	}
   649  	return result, nil
   650  }
   651  
   652  // POST /servers/{id}/private_networks
   653  func (api *API) AssignServerPrivateNetwork(server_id string, pn_id string) (*Server, error) {
   654  	req := new(Identity)
   655  	req.Id = pn_id
   656  	result := new(Server)
   657  	url := createUrl(api, serverPathSegment, server_id, "private_networks")
   658  	err := api.Client.Post(url, &req, &result, http.StatusAccepted)
   659  	if err != nil {
   660  		return nil, err
   661  	}
   662  	result.api = api
   663  	result.decodeRaws()
   664  	return result, nil
   665  }
   666  
   667  // GET /servers/{id}/private_networks/{id}
   668  func (api *API) GetServerPrivateNetwork(server_id string, pn_id string) (*PrivateNetwork, error) {
   669  	result := new(PrivateNetwork)
   670  	url := createUrl(api, serverPathSegment, server_id, "private_networks", pn_id)
   671  	err := api.Client.Get(url, &result, http.StatusOK)
   672  	if err != nil {
   673  		return nil, err
   674  	}
   675  	result.api = api
   676  	return result, nil
   677  }
   678  
   679  // DELETE /servers/{id}/private_networks/{id}
   680  func (api *API) RemoveServerPrivateNetwork(server_id string, pn_id string) (*Server, error) {
   681  	result := new(Server)
   682  	url := createUrl(api, serverPathSegment, server_id, "private_networks", pn_id)
   683  	err := api.Client.Delete(url, nil, &result, http.StatusAccepted)
   684  	if err != nil {
   685  		return nil, err
   686  	}
   687  	result.api = api
   688  	result.decodeRaws()
   689  	return result, nil
   690  }
   691  
   692  // GET /servers/{server_id}/ips/{ip_id}/load_balancers
   693  func (api *API) ListServerIpLoadBalancers(server_id string, ip_id string) ([]Identity, error) {
   694  	result := []Identity{}
   695  	url := createUrl(api, serverPathSegment, server_id, "ips", ip_id, "load_balancers")
   696  	err := api.Client.Get(url, &result, http.StatusOK)
   697  	if err != nil {
   698  		return nil, err
   699  	}
   700  	return result, nil
   701  }
   702  
   703  // POST /servers/{server_id}/ips/{ip_id}/load_balancers
   704  func (api *API) AssignServerIpLoadBalancer(server_id string, ip_id string, lb_id string) (*Server, error) {
   705  	req := struct {
   706  		LbId string `json:"load_balancer_id"`
   707  	}{lb_id}
   708  	result := new(Server)
   709  	url := createUrl(api, serverPathSegment, server_id, "ips", ip_id, "load_balancers")
   710  	err := api.Client.Post(url, &req, &result, http.StatusAccepted)
   711  	if err != nil {
   712  		return nil, err
   713  	}
   714  	result.api = api
   715  	result.decodeRaws()
   716  	return result, nil
   717  }
   718  
   719  // DELETE /servers/{server_id}/ips/{ip_id}/load_balancers
   720  func (api *API) UnassignServerIpLoadBalancer(server_id string, ip_id string, lb_id string) (*Server, error) {
   721  	result := new(Server)
   722  	url := createUrl(api, serverPathSegment, server_id, "ips", ip_id, "load_balancers", lb_id)
   723  	err := api.Client.Delete(url, nil, &result, http.StatusAccepted)
   724  	if err != nil {
   725  		return nil, err
   726  	}
   727  	result.api = api
   728  	result.decodeRaws()
   729  	return result, nil
   730  }
   731  
   732  // GET /servers/{server_id}/ips/{ip_id}/firewall_policy
   733  func (api *API) GetServerIpFirewallPolicy(server_id string, ip_id string) (*Identity, error) {
   734  	result := new(Identity)
   735  	url := createUrl(api, serverPathSegment, server_id, "ips", ip_id, "firewall_policy")
   736  	err := api.Client.Get(url, &result, http.StatusOK)
   737  	if err != nil {
   738  		return nil, err
   739  	}
   740  	return result, nil
   741  }
   742  
   743  // PUT /servers/{server_id}/ips/{ip_id}/firewall_policy
   744  func (api *API) AssignServerIpFirewallPolicy(server_id string, ip_id string, fp_id string) (*Server, error) {
   745  	req := idField{fp_id}
   746  	result := new(Server)
   747  	url := createUrl(api, serverPathSegment, server_id, "ips", ip_id, "firewall_policy")
   748  	err := api.Client.Put(url, &req, &result, http.StatusAccepted)
   749  	if err != nil {
   750  		return nil, err
   751  	}
   752  	result.api = api
   753  	result.decodeRaws()
   754  	return result, nil
   755  }
   756  
   757  // GET /servers/{id}/snapshots
   758  func (api *API) GetServerSnapshot(server_id string) (*ServerSnapshot, error) {
   759  	result := new(ServerSnapshot)
   760  	url := createUrl(api, serverPathSegment, server_id, "snapshots")
   761  	err := api.Client.Get(url, &result, http.StatusOK)
   762  	if err != nil {
   763  		return nil, err
   764  	}
   765  	return result, nil
   766  }
   767  
   768  // POST /servers/{id}/snapshots
   769  func (api *API) CreateServerSnapshot(server_id string) (*Server, error) {
   770  	result := new(Server)
   771  	url := createUrl(api, serverPathSegment, server_id, "snapshots")
   772  	err := api.Client.Post(url, nil, &result, http.StatusAccepted)
   773  	if err != nil {
   774  		return nil, err
   775  	}
   776  	result.api = api
   777  	result.decodeRaws()
   778  	return result, nil
   779  }
   780  
   781  // PUT /servers/{server_id}/snapshots/{snapshot_id}
   782  func (api *API) RestoreServerSnapshot(server_id string, snapshot_id string) (*Server, error) {
   783  	result := new(Server)
   784  	url := createUrl(api, serverPathSegment, server_id, "snapshots", snapshot_id)
   785  	err := api.Client.Put(url, nil, &result, http.StatusAccepted)
   786  	if err != nil {
   787  		return nil, err
   788  	}
   789  	result.api = api
   790  	result.decodeRaws()
   791  	return result, nil
   792  }
   793  
   794  // DELETE /servers/{server_id}/snapshots/{snapshot_id}
   795  func (api *API) DeleteServerSnapshot(server_id string, snapshot_id string) (*Server, error) {
   796  	result := new(Server)
   797  	url := createUrl(api, serverPathSegment, server_id, "snapshots", snapshot_id)
   798  	err := api.Client.Delete(url, nil, &result, http.StatusAccepted)
   799  	if err != nil {
   800  		return nil, err
   801  	}
   802  	result.api = api
   803  	result.decodeRaws()
   804  	return result, nil
   805  }
   806  
   807  // POST /servers/{server_id}/clone
   808  func (api *API) CloneServer(server_id string, new_name string, datacenter_id string) (*Server, error) {
   809  	data := struct {
   810  		Name         string `json:"name"`
   811  		DatacenterId string `json:"datacenter_id,omitempty"`
   812  	}{Name: new_name, DatacenterId: datacenter_id}
   813  	result := new(Server)
   814  	url := createUrl(api, serverPathSegment, server_id, "clone")
   815  	err := api.Client.Post(url, &data, &result, http.StatusAccepted)
   816  	if err != nil {
   817  		return nil, err
   818  	}
   819  	result.api = api
   820  	result.decodeRaws()
   821  	return result, nil
   822  }
   823  
   824  // GET /servers/baremetal_models
   825  func (api *API) ListBaremetalModels() ([]BaremetalModel, error) {
   826  	url := createUrl(api, serverPathSegment, baremetalSegment)
   827  	res := []BaremetalModel{}
   828  	err := api.Client.Get(url, &res, http.StatusOK)
   829  	if err != nil {
   830  		return nil, err
   831  	}
   832  	for index, _ := range res {
   833  		res[index].api = api
   834  	}
   835  	return res, nil
   836  }
   837  
   838  // GET /servers/baremetal_models/{id}
   839  func (api *API) GetBaremetalModel(bm_id string) (*BaremetalModel, error) {
   840  	res := new(BaremetalModel)
   841  	url := createUrl(api, serverPathSegment, baremetalSegment, bm_id)
   842  	err := api.Client.Get(url, &res, http.StatusOK)
   843  	if err != nil {
   844  		return nil, err
   845  	}
   846  	//	res.api = api
   847  	return res, nil
   848  }
   849  
   850  func (s *Server) GetState() (string, error) {
   851  	st, err := s.api.GetServerStatus(s.Id)
   852  	if st == nil {
   853  		return "", err
   854  	}
   855  	return st.State, err
   856  }
   857  
   858  func (server *Server) decodeRaws() {
   859  	if server.AlertsRaw != nil {
   860  		server.Alerts = new(ServerAlerts)
   861  		var sad serverAlertDetails
   862  		if err := json.Unmarshal(*server.AlertsRaw, &sad); err == nil {
   863  			server.Alerts.AlertDetails = &sad
   864  			return
   865  		}
   866  		var sams []serverAlertSummary
   867  		if err := json.Unmarshal(*server.AlertsRaw, &sams); err == nil {
   868  			server.Alerts.AlertSummary = sams
   869  		}
   870  	}
   871  }