package service import ( "context" "fmt" "oci-portal/internal/oci" ) // ChangeVnicPublicIP 更换指定 VNIC 的临时公网 IP,返回新地址(旧保留 IP 自动解绑)。 func (s *OciConfigService) ChangeVnicPublicIP(ctx context.Context, id uint, region, vnicID string) (string, error) { if vnicID == "" { return "", fmt.Errorf("change vnic public ip: vnicId is required") } cred, err := s.credentialsByID(ctx, id) if err != nil { return "", err } return s.client.ChangeVnicPublicIP(ctx, cred, region, vnicID) } // ChangeInstancePublicIP 更换实例主 VNIC 的临时公网 IP,返回新地址。 func (s *OciConfigService) ChangeInstancePublicIP(ctx context.Context, id uint, region, instanceID string) (string, error) { cred, err := s.credentialsByID(ctx, id) if err != nil { return "", err } return s.client.ChangeInstancePublicIP(ctx, cred, region, instanceID) } // AddInstanceIpv6 为实例主 VNIC 分配 IPv6 地址;address 为空时自动分配。 func (s *OciConfigService) AddInstanceIpv6(ctx context.Context, id uint, region, instanceID, address string) (string, error) { cred, err := s.credentialsByID(ctx, id) if err != nil { return "", err } return s.client.AddInstanceIpv6(ctx, cred, region, instanceID, address) } // DeleteInstanceIpv6 取消分配实例上的指定 IPv6 地址。 func (s *OciConfigService) DeleteInstanceIpv6(ctx context.Context, id uint, region, instanceID, address string) error { if address == "" { return fmt.Errorf("delete ipv6: address is required") } cred, err := s.credentialsByID(ctx, id) if err != nil { return err } return s.client.DeleteInstanceIpv6(ctx, cred, region, instanceID, address) } // InstanceVnics 列出实例的全部 VNIC。 func (s *OciConfigService) InstanceVnics(ctx context.Context, id uint, region, instanceID string) ([]oci.Vnic, error) { cred, err := s.credentialsByID(ctx, id) if err != nil { return nil, err } return s.client.ListInstanceVnics(ctx, cred, region, instanceID) } // AttachVnic 为实例附加次要 VNIC;选了保留 IP 时由后台等网卡就绪后绑定。 func (s *OciConfigService) AttachVnic(ctx context.Context, id uint, region, instanceID string, in oci.AttachVnicInput) (oci.Vnic, error) { if instanceID == "" || in.SubnetID == "" { return oci.Vnic{}, fmt.Errorf("attach vnic: instanceId and subnetId are required") } cred, err := s.credentialsByID(ctx, id) if err != nil { return oci.Vnic{}, err } vnic, err := s.client.AttachVnic(ctx, cred, region, instanceID, in) if err != nil { return vnic, err } if in.ReservedPublicIPID != "" { s.goBind(func() { s.bindReservedIPToVnicWhenReady(cred, region, instanceID, vnic.AttachmentID, in.ReservedPublicIPID) }) } return vnic, nil } // DetachVnic 分离 VNIC 附加关系(主 VNIC 由 OCI 拒绝)。 func (s *OciConfigService) DetachVnic(ctx context.Context, id uint, region, attachmentID string) error { cred, err := s.credentialsByID(ctx, id) if err != nil { return err } return s.client.DetachVnic(ctx, cred, region, attachmentID) } // AddVnicIpv6 为指定 VNIC 分配 IPv6;address 留空自动分配。 func (s *OciConfigService) AddVnicIpv6(ctx context.Context, id uint, region, vnicID, address string) (string, error) { if vnicID == "" { return "", fmt.Errorf("add vnic ipv6: vnicId is required") } cred, err := s.credentialsByID(ctx, id) if err != nil { return "", err } return s.client.AddVnicIpv6(ctx, cred, region, vnicID, address) } // BootVolumeAttachments 列出实例的引导卷挂载。 func (s *OciConfigService) BootVolumeAttachments(ctx context.Context, id uint, region, instanceID string) ([]oci.BootVolumeAttachment, error) { cred, err := s.credentialsByID(ctx, id) if err != nil { return nil, err } return s.client.ListBootVolumeAttachments(ctx, cred, region, instanceID) } // AttachBootVolume 为实例挂载引导卷(实例需 STOPPED)。 func (s *OciConfigService) AttachBootVolume(ctx context.Context, id uint, region, instanceID, bootVolumeID string) (oci.BootVolumeAttachment, error) { if instanceID == "" || bootVolumeID == "" { return oci.BootVolumeAttachment{}, fmt.Errorf("attach boot volume: instanceId and bootVolumeId are required") } cred, err := s.credentialsByID(ctx, id) if err != nil { return oci.BootVolumeAttachment{}, err } return s.client.AttachBootVolume(ctx, cred, region, instanceID, bootVolumeID) } // DetachBootVolume 分离引导卷挂载(实例需 STOPPED)。 func (s *OciConfigService) DetachBootVolume(ctx context.Context, id uint, region, attachmentID string) error { cred, err := s.credentialsByID(ctx, id) if err != nil { return err } return s.client.DetachBootVolume(ctx, cred, region, attachmentID) } // ReplaceBootVolume 替换实例引导卷(实例需 STOPPED)。 func (s *OciConfigService) ReplaceBootVolume(ctx context.Context, id uint, region, instanceID, bootVolumeID string) (oci.BootVolumeAttachment, error) { if instanceID == "" || bootVolumeID == "" { return oci.BootVolumeAttachment{}, fmt.Errorf("replace boot volume: instanceId and bootVolumeId are required") } cred, err := s.credentialsByID(ctx, id) if err != nil { return oci.BootVolumeAttachment{}, err } return s.client.ReplaceBootVolume(ctx, cred, region, instanceID, bootVolumeID) } // BlockVolumes 列出块存储卷;compartmentID 为空表示租户根。 func (s *OciConfigService) BlockVolumes(ctx context.Context, id uint, region, availabilityDomain, compartmentID string) ([]oci.BlockVolume, error) { cred, err := s.credentialsInCompartment(ctx, id, compartmentID) if err != nil { return nil, err } return s.client.ListBlockVolumes(ctx, cred, region, availabilityDomain) } // VolumeAttachments 列出实例的块卷挂载。 func (s *OciConfigService) VolumeAttachments(ctx context.Context, id uint, region, instanceID string) ([]oci.VolumeAttachment, error) { cred, err := s.credentialsByID(ctx, id) if err != nil { return nil, err } return s.client.ListVolumeAttachments(ctx, cred, region, instanceID) } // AttachVolume 为实例附加块卷。 func (s *OciConfigService) AttachVolume(ctx context.Context, id uint, region, instanceID, volumeID string, readOnly bool) (oci.VolumeAttachment, error) { if instanceID == "" || volumeID == "" { return oci.VolumeAttachment{}, fmt.Errorf("attach volume: instanceId and volumeId are required") } cred, err := s.credentialsByID(ctx, id) if err != nil { return oci.VolumeAttachment{}, err } return s.client.AttachVolume(ctx, cred, region, instanceID, volumeID, readOnly) } // DetachVolume 分离块卷挂载。 func (s *OciConfigService) DetachVolume(ctx context.Context, id uint, region, attachmentID string) error { cred, err := s.credentialsByID(ctx, id) if err != nil { return err } return s.client.DetachVolume(ctx, cred, region, attachmentID) }