{"action":"created","comment":{"url":"https://api.github.com/repos/stratis-storage/stratisd/pulls/comments/96661125","pull_request_review_id":17239856,"id":96661125,"diff_hunk":"@@ -4,262 +4,365 @@\n \n use std::cmp::Ordering;\n use std::str::from_utf8;\n+use std::fs::File;\n+use std::io::{Read, Seek, SeekFrom, Write};\n \n use byteorder::ByteOrder;\n use byteorder::LittleEndian;\n-\n use crc::crc32;\n-\n use time::Timespec;\n-\n use uuid::Uuid;\n \n-use consts::SECTOR_SIZE;\n-\n use types::Sectors;\n-use types::SectorOffset;\n-\n use super::engine::DevOwnership;\n+use consts::SECTOR_SIZE;\n+use engine::{EngineResult, EngineError, ErrorEnum};\n+use super::blockdev::BDA_STATIC_HDR_SIZE;\n \n-const MDA_OFFSETS: [usize; 4] = [8, 12, 16, 20];\n const MDA_RESERVED_SIZE: Sectors = Sectors(2048 * 3); // = 3 MiB\n+const NUM_MDA_REGIONS: u64 = 4;\n+const MDA_REGION_HDR_SIZE: usize = 32;\n pub const MIN_MDA_SIZE: Sectors = Sectors(2040);\n-const NUM_MDA_COPIES: u64 = 2;\n const STRAT_MAGIC: &'static [u8] = b\"!Stra0tis\\x86\\xff\\x02^\\x41rh\";\n \n-#[derive(Debug, Clone, Copy)]\n-pub struct MDA {\n-    // Recorded values\n-    pub crc: u32,\n-    pub last_updated: Timespec,\n-    pub used: u32,\n-\n-    // Computed values\n-    pub offset: SectorOffset, // From start of MDA, not BDA\n+#[derive(Debug, Clone)]\n+pub struct BDA {\n+    pub header: StaticHeader,\n+    pub regions: MDARegions,\n }\n \n-impl MDA {\n-    pub fn new(offset: SectorOffset) -> MDA {\n-        MDA {\n-            crc: 0,\n-            last_updated: Timespec::new(0, 0),\n-            used: 0,\n-            offset: offset,\n-        }\n-    }\n-\n-    fn offsets(offset: usize) -> (usize, usize, usize, usize) {\n-        (offset + MDA_OFFSETS[0],\n-         offset + MDA_OFFSETS[1],\n-         offset + MDA_OFFSETS[2],\n-         offset + MDA_OFFSETS[3])\n-    }\n-\n-    /// Write out recorded values to buf at offset.\n-    pub fn write(&self, buf: &mut [u8], offset: usize) {\n-        let (offset1, offset2, offset3, offset4) = MDA::offsets(offset);\n-\n-        let last_updated = self.last_updated;\n-        LittleEndian::write_u64(&mut buf[offset..offset1], last_updated.sec as u64);\n-        LittleEndian::write_u32(&mut buf[offset1..offset2], last_updated.nsec as u32);\n-\n-        LittleEndian::write_u32(&mut buf[offset2..offset3], self.used);\n-        LittleEndian::write_u32(&mut buf[offset3..offset4], self.crc);\n+impl BDA {\n+    pub fn initialize(mut f: &mut File, header: StaticHeader) -> EngineResult<BDA> {\n+        let zeroed = [0u8; BDA_STATIC_HDR_SIZE as usize];\n+        let hdr_buf = header.to_buf();\n+\n+        // Write 8K header. Static_Header copies go in sectors 1 and 9.\n+        try!(f.seek(SeekFrom::Start(0)));\n+        try!(f.write_all(&zeroed[..SECTOR_SIZE as usize]));\n+        try!(f.write_all(&hdr_buf));\n+        try!(f.write_all(&zeroed[(SECTOR_SIZE * 7) as usize..]));\n+        try!(f.flush());\n+        try!(f.write_all(&hdr_buf));\n+        try!(f.write_all(&zeroed[(SECTOR_SIZE * 6) as usize..]));\n+        try!(f.flush());\n+\n+        let regions = try!(MDARegions::initialize(&header, &mut f));\n+\n+        Ok(BDA {\n+            header: header,\n+            regions: regions,\n+        })\n     }\n \n-    /// Read recorded values into buffer at buf_offset.\n-    pub fn read(buf: &[u8], buf_offset: usize, offset: SectorOffset) -> MDA {\n-        let (offset1, offset2, offset3, offset4) = MDA::offsets(buf_offset);\n+    pub fn load(f: &mut File, header: StaticHeader) -> EngineResult<BDA> {\n+        let regions = try!(MDARegions::load(&header, f));\n \n-        MDA {\n-            last_updated: Timespec::new(LittleEndian::read_u64(&buf[buf_offset..offset1]) as i64,\n-                                        LittleEndian::read_u32(&buf[offset1..offset2]) as i32),\n-            used: LittleEndian::read_u32(&buf[offset2..offset3]),\n-            crc: LittleEndian::read_u32(&buf[offset3..offset4]),\n-            offset: offset,\n-        }\n-    }\n-}\n-\n-#[derive(Debug, Clone)]\n-pub struct MDAGroup {\n-    pub mda_length: u32,\n-    mdaa: MDA,\n-    mdab: MDA,\n-}\n-\n-impl MDAGroup {\n-    pub fn new(size: Sectors) -> MDAGroup {\n-        MDAGroup {\n-            mda_length: ((*size / NUM_MDA_COPIES) * SECTOR_SIZE) as u32,\n-            mdaa: MDA::new(SectorOffset(0)),\n-            mdab: MDA::new(SectorOffset(*size / NUM_MDA_COPIES)),\n-        }\n+        Ok(BDA {\n+            header: header,\n+            regions: regions,\n+        })\n     }\n \n-    /// Read MDAGroup from buf at offset.\n-    /// Use size to calculate values for each MDA in the group.\n-    pub fn read(buf: &[u8], offset: usize, size: Sectors) -> MDAGroup {\n-        MDAGroup {\n-            mda_length: ((*size / NUM_MDA_COPIES) * SECTOR_SIZE) as u32,\n-            mdaa: MDA::read(&buf, offset, SectorOffset(0)),\n-            mdab: MDA::read(&buf, offset + 32, SectorOffset(*size / NUM_MDA_COPIES)),\n-        }\n-    }\n+    // Wipe metadata\n+    pub fn wipe(f: &mut File) -> EngineResult<()> {\n+        let zeroed = [0u8; BDA_STATIC_HDR_SIZE as usize];\n \n-    /// Write MDAGroup to buf at offset.\n-    pub fn write(&self, buf: &mut [u8], offset: usize) {\n-        self.mdaa.write(buf, offset);\n-        self.mdab.write(buf, offset + 32);\n+        // Wiping Static Header should do it\n+        try!(f.seek(SeekFrom::Start(0)));\n+        try!(f.write_all(&zeroed));\n+        try!(f.flush());\n+        Ok(())\n     }\n \n-    /// Return the most recently timestamped MDA.\n-    pub fn most_recent(&self) -> &MDA {\n-        match self.mdaa.last_updated.cmp(&self.mdab.last_updated) {\n-            Ordering::Less => &self.mdab,\n-            Ordering::Greater => &self.mdaa,\n-            _ => &self.mdab,\n-        }\n-    }\n+    pub fn save_state(&mut self,\n+                      time: &Timespec,\n+                      metadata: &[u8],\n+                      mut f: &mut File)\n+                      -> EngineResult<()> {\n+        try!(self.regions.save(time, metadata, &mut f));\n \n-    /// Return the least recently timestamped MDA.\n-    pub fn least_recent(&mut self) -> &mut MDA {\n-        match self.mdaa.last_updated.cmp(&self.mdab.last_updated) {\n-            Ordering::Less => &mut self.mdaa,\n-            Ordering::Greater => &mut self.mdab,\n-            _ => &mut self.mdaa,\n-        }\n+        Ok(())\n     }\n }\n \n #[derive(Debug, Clone)]\n-pub struct SigBlock {\n-    pub total_size: Sectors,\n+pub struct StaticHeader {\n+    pub blkdev_size: Sectors,\n     pub pool_uuid: Uuid,\n     pub dev_uuid: Uuid,\n-    pub mda: MDAGroup,\n-    pub mda_sectors: Sectors,\n-    pub reserved_sectors: Sectors,\n+    pub mda_size: Sectors,\n+    pub reserved_size: Sectors,\n+    pub flags: u64,\n }\n \n-impl SigBlock {\n+impl StaticHeader {\n     pub fn new(pool_uuid: &Uuid,\n                dev_uuid: &Uuid,\n                mda_size: Sectors,\n-               total_size: Sectors)\n-               -> SigBlock {\n-        SigBlock {\n-            mda: MDAGroup::new(mda_size),\n+               blkdev_size: Sectors)\n+               -> StaticHeader {\n+        StaticHeader {\n+            blkdev_size: blkdev_size,\n             pool_uuid: pool_uuid.clone(),\n             dev_uuid: dev_uuid.clone(),\n-            total_size: total_size,\n-            mda_sectors: mda_size,\n-            reserved_sectors: MDA_RESERVED_SIZE,\n+            mda_size: mda_size,\n+            reserved_size: MDA_RESERVED_SIZE,\n+            flags: 0,\n         }\n     }\n \n-    /// Write SigBlock to buf at offset.\n-    pub fn write(&self, buf: &mut [u8], offset: usize) {\n-        buf[offset + 4..offset + 20].clone_from_slice(STRAT_MAGIC);\n-        LittleEndian::write_u64(&mut buf[offset + 20..offset + 28], *self.total_size);\n-        buf[offset + 32..offset + 64]\n-            .clone_from_slice(self.pool_uuid.simple().to_string().as_bytes());\n-        buf[offset + 64..offset + 96]\n-            .clone_from_slice(self.dev_uuid.simple().to_string().as_bytes());\n-        self.mda.write(buf, offset + 96);\n-        LittleEndian::write_u32(&mut buf[offset + 160..offset + 164],\n-                                *self.mda_sectors as u32);\n-        LittleEndian::write_u32(&mut buf[offset + 164..offset + 168],\n-                                *self.reserved_sectors as u32);\n-\n-        let hdr_crc = crc32::checksum_ieee(&buf[offset + 4..offset + SECTOR_SIZE as usize]);\n-        LittleEndian::write_u32(&mut buf[offset..offset + 4], hdr_crc);\n+    /// Generate a buf suitable for writing to blockdev\n+    pub fn to_buf(&self) -> [u8; SECTOR_SIZE as usize] {\n+        let mut buf = [0u8; SECTOR_SIZE as usize];\n+        buf[4..20].clone_from_slice(STRAT_MAGIC);\n+        LittleEndian::write_u64(&mut buf[20..28], *self.blkdev_size);\n+        buf[32..64].clone_from_slice(self.pool_uuid.simple().to_string().as_bytes());\n+        buf[64..96].clone_from_slice(self.dev_uuid.simple().to_string().as_bytes());\n+        LittleEndian::write_u32(&mut buf[160..164], *self.mda_size as u32);\n+        LittleEndian::write_u32(&mut buf[164..168], *self.reserved_size as u32);\n+\n+        let hdr_crc = crc32::checksum_ieee(&buf[4..SECTOR_SIZE as usize]);\n+        LittleEndian::write_u32(&mut buf[..4], hdr_crc);\n+        buf\n     }\n \n-    /// Read SigBlock from buf at offset.\n-    pub fn read(buf: &[u8], offset: usize, total_size: Sectors) -> Result<SigBlock, String> {\n-        if &buf[offset + 4..offset + 20] != STRAT_MAGIC {\n-            return Err(\"not a Stratis device\".into());\n+    /// Build a StaticHeader from a buf read from blockdev\n+    pub fn from_buf(buf: &[u8]) -> EngineResult<StaticHeader> {\n+        if &buf[4..20] != STRAT_MAGIC {\n+            return Err(EngineError::Engine(ErrorEnum::Invalid, \"not a Stratis device\".into()));\n         }\n \n-        let crc = crc32::checksum_ieee(&buf[offset + 4..offset + SECTOR_SIZE as usize]);\n-        if crc != LittleEndian::read_u32(&buf[offset..offset + 4]) {\n-            return Err(\"header CRC invalid\".into());\n+        let crc = crc32::checksum_ieee(&buf[4..SECTOR_SIZE as usize]);\n+        if crc != LittleEndian::read_u32(&buf[..4]) {\n+            return Err(EngineError::Engine(ErrorEnum::Invalid, \"header CRC invalid\".into()));\n         }\n \n-        let pool_uuid = try!(Uuid::parse_str(from_utf8(&buf[offset + 32..offset + 64]).unwrap())\n-            .map_err(|_| \"invalid pool uuid\"));\n-        let dev_uuid = try!(Uuid::parse_str(from_utf8(&buf[offset + 64..offset + 96]).unwrap())\n-            .map_err(|_| \"invalid dev uuid\"));\n+        let blkdev_size = Sectors(LittleEndian::read_u64(&buf[20..28]) as u64);\n \n-        let mda_size = Sectors(LittleEndian::read_u32(&buf[offset + 160..offset + 164]) as u64);\n+        let pool_uuid = try!(Uuid::parse_str(from_utf8(&buf[32..64]).unwrap())\n+            .map_err(|_| EngineError::Engine(ErrorEnum::Invalid, \"invalid pool uuid\".into())));\n+        let dev_uuid = try!(Uuid::parse_str(from_utf8(&buf[64..96]).unwrap())\n+            .map_err(|_| EngineError::Engine(ErrorEnum::Invalid, \"invalid dev uuid\".into())));\n \n-        match validate_mda_size(mda_size) {\n-            None => {}\n-            Some(err) => {\n-                return Err(err.into());\n-            }\n-        };\n \n-        Ok(SigBlock {\n-            mda: MDAGroup::read(buf, offset + 96, mda_size),\n+        let mda_size = Sectors(LittleEndian::read_u64(&buf[96..104]) as u64);\n+\n+        try!(validate_mda_size(mda_size));\n+\n+        Ok(StaticHeader {\n             pool_uuid: pool_uuid,\n             dev_uuid: dev_uuid,\n-            total_size: total_size,\n-            mda_sectors: mda_size,\n-            reserved_sectors:\n-                Sectors(LittleEndian::read_u32(&buf[offset + 164..offset + 168]) as u64),\n+            blkdev_size: blkdev_size,\n+            mda_size: mda_size,\n+            reserved_size: Sectors(LittleEndian::read_u64(&buf[104..112]) as u64),\n+            flags: 0,\n         })\n     }\n \n-    /// Read from Stratis magic number area in buf at offset.\n-    pub fn read_strat_magic(buf: &[u8], offset: usize) -> &[u8] {\n-        &buf[offset + 4..offset + 20]\n-    }\n-\n     /// Read pool uuid from buf at offset.\n     /// Return an error if the data can't be interpreted as a Uuid.\n-    pub fn read_pool_uuid(buf: &[u8], offset: usize) -> Result<Uuid, String> {\n-        Uuid::parse_str(from_utf8(&buf[offset + 32..offset + 64]).unwrap())\n-            .map_err(|_| \"invalid pool uuid\".into())\n+    pub fn read_pool_uuid(buf: &[u8; BDA_STATIC_HDR_SIZE as usize]) -> EngineResult<Uuid> {\n+        Uuid::parse_str(from_utf8(&buf[SECTOR_SIZE as usize + 32..SECTOR_SIZE as usize + 64])\n+                .unwrap())\n+            .map_err(|_| EngineError::Engine(ErrorEnum::Invalid, \"invalid pool uuid\".into()))\n     }\n \n     /// Determine the ownership of a device based on data in buf.\n-    pub fn determine_ownership(buf: &[u8]) -> Result<DevOwnership, String> {\n-        let mut ownership = DevOwnership::Unowned;\n-        if SigBlock::read_strat_magic(&buf, SECTOR_SIZE as usize) == STRAT_MAGIC {\n-            ownership = match SigBlock::read_pool_uuid(&buf, SECTOR_SIZE as usize) {\n-                Ok(pool_id) => DevOwnership::Ours(pool_id),\n-                Err(_) => {\n-                    let error_message = format!(\"unable to read pool uuid\");\n-                    return Err(error_message.into());\n-                }\n-            }\n+    pub fn determine_ownership(buf: &[u8; BDA_STATIC_HDR_SIZE as usize])\n+                               -> EngineResult<DevOwnership> {\n+        if &buf[SECTOR_SIZE as usize + 4..SECTOR_SIZE as usize + 20] == STRAT_MAGIC {\n+            Ok(DevOwnership::Ours(try!(StaticHeader::read_pool_uuid(&buf))))\n         } else {\n             if buf.iter().any(|x| *x != 0) {\n-                ownership = DevOwnership::Theirs;\n+                Ok(DevOwnership::Theirs)\n+            } else {\n+                Ok(DevOwnership::Unowned)\n+            }\n+        }\n+    }\n+}\n+\n+#[derive(Debug, Clone)]\n+pub struct MDARegions {\n+    // Spec defines 4 regions, but regions 2 & 3 are duplicates of 0 and 1 respectively\n+    pub region_size: Sectors,\n+    mdas: [MDAHeader; 2],","path":"src/engine/strat_engine/metadata.rs","position":null,"original_position":358,"commit_id":"4019ea9f104a4c33d1b6a2f3dfc44c74152f5ea7","original_commit_id":"aca6d3aa4935a68ac978b652bdcdd7f1be89c27e","user":{"login":"mulkieran","id":1218366,"avatar_url":"https://avatars.githubusercontent.com/u/1218366?v=3","gravatar_id":"","url":"https://api.github.com/users/mulkieran","html_url":"https://github.com/mulkieran","followers_url":"https://api.github.com/users/mulkieran/followers","following_url":"https://api.github.com/users/mulkieran/following{/other_user}","gists_url":"https://api.github.com/users/mulkieran/gists{/gist_id}","starred_url":"https://api.github.com/users/mulkieran/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mulkieran/subscriptions","organizations_url":"https://api.github.com/users/mulkieran/orgs","repos_url":"https://api.github.com/users/mulkieran/repos","events_url":"https://api.github.com/users/mulkieran/events{/privacy}","received_events_url":"https://api.github.com/users/mulkieran/received_events","type":"User","site_admin":false},"body":"Maybe the 2 should be a constant, or a derived number.","created_at":"2017-01-18T15:34:01Z","updated_at":"2017-01-18T15:51:43Z","html_url":"https://github.com/stratis-storage/stratisd/pull/207#discussion_r96661125","pull_request_url":"https://api.github.com/repos/stratis-storage/stratisd/pulls/207","_links":{"self":{"href":"https://api.github.com/repos/stratis-storage/stratisd/pulls/comments/96661125"},"html":{"href":"https://github.com/stratis-storage/stratisd/pull/207#discussion_r96661125"},"pull_request":{"href":"https://api.github.com/repos/stratis-storage/stratisd/pulls/207"}}},"pull_request":{"url":"https://api.github.com/repos/stratis-storage/stratisd/pulls/207","id":101786856,"html_url":"https://github.com/stratis-storage/stratisd/pull/207","diff_url":"https://github.com/stratis-storage/stratisd/pull/207.diff","patch_url":"https://github.com/stratis-storage/stratisd/pull/207.patch","issue_url":"https://api.github.com/repos/stratis-storage/stratisd/issues/207","number":207,"state":"open","locked":false,"title":"Update blockdev code for latest metadata format (0.7.5)","user":{"login":"agrover","id":2305,"avatar_url":"https://avatars.githubusercontent.com/u/2305?v=3","gravatar_id":"","url":"https://api.github.com/users/agrover","html_url":"https://github.com/agrover","followers_url":"https://api.github.com/users/agrover/followers","following_url":"https://api.github.com/users/agrover/following{/other_user}","gists_url":"https://api.github.com/users/agrover/gists{/gist_id}","starred_url":"https://api.github.com/users/agrover/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/agrover/subscriptions","organizations_url":"https://api.github.com/users/agrover/orgs","repos_url":"https://api.github.com/users/agrover/repos","events_url":"https://api.github.com/users/agrover/events{/privacy}","received_events_url":"https://api.github.com/users/agrover/received_events","type":"User","site_admin":false},"body":"WIP for the blockdev stuff I've been working on. It delves a little into some error rework, and then gets into the heart of the changes.","created_at":"2017-01-17T02:24:17Z","updated_at":"2017-01-18T15:51:43Z","closed_at":null,"merged_at":null,"merge_commit_sha":"f3c0418eaeeb5157b13fe543b05b1368b47a9463","assignee":null,"assignees":[],"milestone":null,"commits_url":"https://api.github.com/repos/stratis-storage/stratisd/pulls/207/commits","review_comments_url":"https://api.github.com/repos/stratis-storage/stratisd/pulls/207/comments","review_comment_url":"https://api.github.com/repos/stratis-storage/stratisd/pulls/comments{/number}","comments_url":"https://api.github.com/repos/stratis-storage/stratisd/issues/207/comments","statuses_url":"https://api.github.com/repos/stratis-storage/stratisd/statuses/4019ea9f104a4c33d1b6a2f3dfc44c74152f5ea7","head":{"label":"agrover:blockdev-wip","ref":"blockdev-wip","sha":"4019ea9f104a4c33d1b6a2f3dfc44c74152f5ea7","user":{"login":"agrover","id":2305,"avatar_url":"https://avatars.githubusercontent.com/u/2305?v=3","gravatar_id":"","url":"https://api.github.com/users/agrover","html_url":"https://github.com/agrover","followers_url":"https://api.github.com/users/agrover/followers","following_url":"https://api.github.com/users/agrover/following{/other_user}","gists_url":"https://api.github.com/users/agrover/gists{/gist_id}","starred_url":"https://api.github.com/users/agrover/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/agrover/subscriptions","organizations_url":"https://api.github.com/users/agrover/orgs","repos_url":"https://api.github.com/users/agrover/repos","events_url":"https://api.github.com/users/agrover/events{/privacy}","received_events_url":"https://api.github.com/users/agrover/received_events","type":"User","site_admin":false},"repo":{"id":68636276,"name":"stratisd","full_name":"agrover/stratisd","owner":{"login":"agrover","id":2305,"avatar_url":"https://avatars.githubusercontent.com/u/2305?v=3","gravatar_id":"","url":"https://api.github.com/users/agrover","html_url":"https://github.com/agrover","followers_url":"https://api.github.com/users/agrover/followers","following_url":"https://api.github.com/users/agrover/following{/other_user}","gists_url":"https://api.github.com/users/agrover/gists{/gist_id}","starred_url":"https://api.github.com/users/agrover/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/agrover/subscriptions","organizations_url":"https://api.github.com/users/agrover/orgs","repos_url":"https://api.github.com/users/agrover/repos","events_url":"https://api.github.com/users/agrover/events{/privacy}","received_events_url":"https://api.github.com/users/agrover/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/agrover/stratisd","description":null,"fork":true,"url":"https://api.github.com/repos/agrover/stratisd","forks_url":"https://api.github.com/repos/agrover/stratisd/forks","keys_url":"https://api.github.com/repos/agrover/stratisd/keys{/key_id}","collaborators_url":"https://api.github.com/repos/agrover/stratisd/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/agrover/stratisd/teams","hooks_url":"https://api.github.com/repos/agrover/stratisd/hooks","issue_events_url":"https://api.github.com/repos/agrover/stratisd/issues/events{/number}","events_url":"https://api.github.com/repos/agrover/stratisd/events","assignees_url":"https://api.github.com/repos/agrover/stratisd/assignees{/user}","branches_url":"https://api.github.com/repos/agrover/stratisd/branches{/branch}","tags_url":"https://api.github.com/repos/agrover/stratisd/tags","blobs_url":"https://api.github.com/repos/agrover/stratisd/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/agrover/stratisd/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/agrover/stratisd/git/refs{/sha}","trees_url":"https://api.github.com/repos/agrover/stratisd/git/trees{/sha}","statuses_url":"https://api.github.com/repos/agrover/stratisd/statuses/{sha}","languages_url":"https://api.github.com/repos/agrover/stratisd/languages","stargazers_url":"https://api.github.com/repos/agrover/stratisd/stargazers","contributors_url":"https://api.github.com/repos/agrover/stratisd/contributors","subscribers_url":"https://api.github.com/repos/agrover/stratisd/subscribers","subscription_url":"https://api.github.com/repos/agrover/stratisd/subscription","commits_url":"https://api.github.com/repos/agrover/stratisd/commits{/sha}","git_commits_url":"https://api.github.com/repos/agrover/stratisd/git/commits{/sha}","comments_url":"https://api.github.com/repos/agrover/stratisd/comments{/number}","issue_comment_url":"https://api.github.com/repos/agrover/stratisd/issues/comments{/number}","contents_url":"https://api.github.com/repos/agrover/stratisd/contents/{+path}","compare_url":"https://api.github.com/repos/agrover/stratisd/compare/{base}...{head}","merges_url":"https://api.github.com/repos/agrover/stratisd/merges","archive_url":"https://api.github.com/repos/agrover/stratisd/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/agrover/stratisd/downloads","issues_url":"https://api.github.com/repos/agrover/stratisd/issues{/number}","pulls_url":"https://api.github.com/repos/agrover/stratisd/pulls{/number}","milestones_url":"https://api.github.com/repos/agrover/stratisd/milestones{/number}","notifications_url":"https://api.github.com/repos/agrover/stratisd/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/agrover/stratisd/labels{/name}","releases_url":"https://api.github.com/repos/agrover/stratisd/releases{/id}","deployments_url":"https://api.github.com/repos/agrover/stratisd/deployments","created_at":"2016-09-19T18:55:49Z","updated_at":"2016-09-19T18:55:51Z","pushed_at":"2017-01-17T23:31:18Z","git_url":"git://github.com/agrover/stratisd.git","ssh_url":"git@github.com:agrover/stratisd.git","clone_url":"https://github.com/agrover/stratisd.git","svn_url":"https://github.com/agrover/stratisd","homepage":null,"size":416,"stargazers_count":0,"watchers_count":0,"language":"Rust","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"stratis-storage:master","ref":"master","sha":"f095cd4b71a98265055aa6b6f6cc9b64799ad3db","user":{"login":"stratis-storage","id":21202300,"avatar_url":"https://avatars.githubusercontent.com/u/21202300?v=3","gravatar_id":"","url":"https://api.github.com/users/stratis-storage","html_url":"https://github.com/stratis-storage","followers_url":"https://api.github.com/users/stratis-storage/followers","following_url":"https://api.github.com/users/stratis-storage/following{/other_user}","gists_url":"https://api.github.com/users/stratis-storage/gists{/gist_id}","starred_url":"https://api.github.com/users/stratis-storage/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/stratis-storage/subscriptions","organizations_url":"https://api.github.com/users/stratis-storage/orgs","repos_url":"https://api.github.com/users/stratis-storage/repos","events_url":"https://api.github.com/users/stratis-storage/events{/privacy}","received_events_url":"https://api.github.com/users/stratis-storage/received_events","type":"Organization","site_admin":false},"repo":{"id":66564704,"name":"stratisd","full_name":"stratis-storage/stratisd","owner":{"login":"stratis-storage","id":21202300,"avatar_url":"https://avatars.githubusercontent.com/u/21202300?v=3","gravatar_id":"","url":"https://api.github.com/users/stratis-storage","html_url":"https://github.com/stratis-storage","followers_url":"https://api.github.com/users/stratis-storage/followers","following_url":"https://api.github.com/users/stratis-storage/following{/other_user}","gists_url":"https://api.github.com/users/stratis-storage/gists{/gist_id}","starred_url":"https://api.github.com/users/stratis-storage/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/stratis-storage/subscriptions","organizations_url":"https://api.github.com/users/stratis-storage/orgs","repos_url":"https://api.github.com/users/stratis-storage/repos","events_url":"https://api.github.com/users/stratis-storage/events{/privacy}","received_events_url":"https://api.github.com/users/stratis-storage/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/stratis-storage/stratisd","description":null,"fork":false,"url":"https://api.github.com/repos/stratis-storage/stratisd","forks_url":"https://api.github.com/repos/stratis-storage/stratisd/forks","keys_url":"https://api.github.com/repos/stratis-storage/stratisd/keys{/key_id}","collaborators_url":"https://api.github.com/repos/stratis-storage/stratisd/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/stratis-storage/stratisd/teams","hooks_url":"https://api.github.com/repos/stratis-storage/stratisd/hooks","issue_events_url":"https://api.github.com/repos/stratis-storage/stratisd/issues/events{/number}","events_url":"https://api.github.com/repos/stratis-storage/stratisd/events","assignees_url":"https://api.github.com/repos/stratis-storage/stratisd/assignees{/user}","branches_url":"https://api.github.com/repos/stratis-storage/stratisd/branches{/branch}","tags_url":"https://api.github.com/repos/stratis-storage/stratisd/tags","blobs_url":"https://api.github.com/repos/stratis-storage/stratisd/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/stratis-storage/stratisd/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/stratis-storage/stratisd/git/refs{/sha}","trees_url":"https://api.github.com/repos/stratis-storage/stratisd/git/trees{/sha}","statuses_url":"https://api.github.com/repos/stratis-storage/stratisd/statuses/{sha}","languages_url":"https://api.github.com/repos/stratis-storage/stratisd/languages","stargazers_url":"https://api.github.com/repos/stratis-storage/stratisd/stargazers","contributors_url":"https://api.github.com/repos/stratis-storage/stratisd/contributors","subscribers_url":"https://api.github.com/repos/stratis-storage/stratisd/subscribers","subscription_url":"https://api.github.com/repos/stratis-storage/stratisd/subscription","commits_url":"https://api.github.com/repos/stratis-storage/stratisd/commits{/sha}","git_commits_url":"https://api.github.com/repos/stratis-storage/stratisd/git/commits{/sha}","comments_url":"https://api.github.com/repos/stratis-storage/stratisd/comments{/number}","issue_comment_url":"https://api.github.com/repos/stratis-storage/stratisd/issues/comments{/number}","contents_url":"https://api.github.com/repos/stratis-storage/stratisd/contents/{+path}","compare_url":"https://api.github.com/repos/stratis-storage/stratisd/compare/{base}...{head}","merges_url":"https://api.github.com/repos/stratis-storage/stratisd/merges","archive_url":"https://api.github.com/repos/stratis-storage/stratisd/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/stratis-storage/stratisd/downloads","issues_url":"https://api.github.com/repos/stratis-storage/stratisd/issues{/number}","pulls_url":"https://api.github.com/repos/stratis-storage/stratisd/pulls{/number}","milestones_url":"https://api.github.com/repos/stratis-storage/stratisd/milestones{/number}","notifications_url":"https://api.github.com/repos/stratis-storage/stratisd/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/stratis-storage/stratisd/labels{/name}","releases_url":"https://api.github.com/repos/stratis-storage/stratisd/releases{/id}","deployments_url":"https://api.github.com/repos/stratis-storage/stratisd/deployments","created_at":"2016-08-25T14:24:19Z","updated_at":"2016-10-25T09:59:05Z","pushed_at":"2017-01-18T14:24:42Z","git_url":"git://github.com/stratis-storage/stratisd.git","ssh_url":"git@github.com:stratis-storage/stratisd.git","clone_url":"https://github.com/stratis-storage/stratisd.git","svn_url":"https://github.com/stratis-storage/stratisd","homepage":null,"size":402,"stargazers_count":1,"watchers_count":1,"language":"Rust","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":4,"mirror_url":null,"open_issues_count":50,"forks":4,"open_issues":50,"watchers":1,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/stratis-storage/stratisd/pulls/207"},"html":{"href":"https://github.com/stratis-storage/stratisd/pull/207"},"issue":{"href":"https://api.github.com/repos/stratis-storage/stratisd/issues/207"},"comments":{"href":"https://api.github.com/repos/stratis-storage/stratisd/issues/207/comments"},"review_comments":{"href":"https://api.github.com/repos/stratis-storage/stratisd/pulls/207/comments"},"review_comment":{"href":"https://api.github.com/repos/stratis-storage/stratisd/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/stratis-storage/stratisd/pulls/207/commits"},"statuses":{"href":"https://api.github.com/repos/stratis-storage/stratisd/statuses/4019ea9f104a4c33d1b6a2f3dfc44c74152f5ea7"}}}}
{"actor":{"display_login":"mulkieran"}}